1. 개발 환경 설정
필요한 도구
- Android Studio (최신 버전)
- Wear OS SDK
- Kotlin Plugin (기본 포함)
Android Studio 설정
- Android Studio 설치
- SDK Manager에서 Wear OS SDK 설치
- Virtual Device Manager에서 Wear OS 에뮬레이터 생성
2. 프로젝트 생성
New Project 생성
File → New → New Project → Wear OS → Empty Activity
프로젝트 구조
wear/
├── src/main/
│ ├── kotlin/
│ │ └── com.example.wearapp/
│ │ └── MainActivity.kt
│ ├── res/
│ │ └── layout/
│ │ └── activity_main.xml
│ └── AndroidManifest.xml
└── build.gradle.kts
3. build.gradle.kts 설정
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.example.wearapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.wearapp"
minSdk = 30 // Wear OS 3.0
targetSdk = 34
versionCode = 1
versionName = "1.0"
}
}
dependencies {
// Wear OS 기본 라이브러리
implementation("androidx.wear:wear:1.3.0")
// Jetpack Compose for Wear OS
implementation("androidx.wear.compose:compose-material:1.3.0")
implementation("androidx.wear.compose:compose-foundation:1.3.0")
// Activity
implementation("androidx.activity:activity-compose:1.8.2")
// Kotlin
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.22")
}
4. MainActivity.kt 기본 구조
전통적인 View 방식
package com.example.wearapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.wear.widget.WearableLinearLayoutManager
import androidx.wear.widget.WearableRecyclerView
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Wear OS 특화 UI 초기화
}
}
Jetpack Compose 방식 (권장)
package com.example.wearapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WearApp()
}
}
}
@Composable
fun WearApp() {
MaterialTheme {
Scaffold(
timeText = { TimeText() }
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Hello Wear OS!",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.title2
)
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = { /* 버튼 클릭 처리 */ }) {
Text("Click Me")
}
}
}
}
}
5. AndroidManifest.xml 설정
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.type.watch" />
<!-- 권한 설정 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault">
<!-- Wear OS 기능 선언 -->
<uses-library
android:name="com.google.android.wearable"
android:required="true" />
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
6. Wear OS UI 컴포넌트
ScalingLazyColumn (스크롤 리스트)
@Composable
fun WearableList() {
ScalingLazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(10) { index ->
Chip(
onClick = { /* 항목 클릭 */ },
label = { Text("Item $index") }
)
}
}
}
Card (카드 UI)
@Composable
fun WearableCard() {
Card(
onClick = { /* 카드 클릭 */ }
) {
Text(
text = "Card Content",
modifier = Modifier.padding(16.dp)
)
}
}
TimeText (상단 시간 표시)
@Composable
fun AppWithTime() {
Scaffold(
timeText = {
TimeText(
timeTextStyle = TimeTextDefaults.timeTextStyle(
fontSize = MaterialTheme.typography.caption1.fontSize
)
)
}
) {
// 앱 콘텐츠
}
}
7. 센서 및 하드웨어 활용
심박수 센서
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
class HeartRateMonitor(context: Context) : SensorEventListener {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val heartRateSensor = sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE)
fun startMonitoring() {
sensorManager.registerListener(
this,
heartRateSensor,
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onSensorChanged(event: SensorEvent?) {
event?.let {
val heartRate = it.values[0]
// 심박수 처리
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
fun stopMonitoring() {
sensorManager.unregisterListener(this)
}
}
가속도계
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
8. 알림 및 컴플리케이션
알림 표시
import android.app.NotificationChannel
import android.app.NotificationManager
import androidx.core.app.NotificationCompat
fun showNotification(context: Context) {
val channelId = "wear_channel"
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
channelId,
"Wear Notifications",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
val notification = NotificationCompat.Builder(context, channelId)
.setContentTitle("Wear OS 알림")
.setContentText("메시지 내용")
.setSmallIcon(R.drawable.ic_notification)
.build()
notificationManager.notify(1, notification)
}
9. 실행 및 디버깅
에뮬레이터에서 실행
- AVD Manager에서 Wear OS 디바이스 생성
- Run → Run ‘wear’ 선택
- 에뮬레이터에서 앱 확인
실제 기기에서 실행
- 갤럭시 워치에서 개발자 옵션 활성화
- ADB 디버깅 활성화
- USB 또는 Wi-Fi로 연결
- Android Studio에서 기기 선택 후 실행
로그 확인
import android.util.Log
Log.d("WearApp", "Debug message")
Log.e("WearApp", "Error message")
10. 최적화 팁
배터리 효율
- 센서는 필요할 때만 활성화
- 백그라운드 작업 최소화
doze
모드 고려
UI/UX
- 원형 디스플레이 고려 (Round/Square 대응)
- 터치 영역 충분히 크게 (최소 48dp)
- 짧은 인터랙션 설계
- Ambient 모드 지원
성능
- 가벼운 이미지 사용
- 불필요한 애니메이션 제거
- 메모리 사용 최소화
11. 유용한 라이브러리
// Health Services (건강 데이터)
implementation("androidx.health:health-services-client:1.0.0-beta03")
// DataStore (데이터 저장)
implementation("androidx.datastore:datastore-preferences:1.0.0")
// Navigation (화면 전환)
implementation("androidx.wear.compose:compose-navigation:1.3.0")
12. 참고 자료