fornewid / ConfDocs

Conference 내용 끄적끄적
4 stars 0 forks source link

Create beautiful, power-efficient apps for Wear OS #20

Closed fornewid closed 1 year ago

fornewid commented 2 years ago

목차

fornewid commented 2 years ago

전년 대비 거의 3배의 활성화 증가율을 보이고 있다. 앱 성능을 측정하고 최적화하기 위한 모범 사례와 함께 현대적이고 전력 효율적인 Wear OS 앱 개발에 대해 알아본다.

  1. Compose for Wear OS: material components, 도구, 그리고 가이드를 제공한다.
  2. 더 작은 장치의 앱은 성능 요구 사항에 주의를 기울여야 한다. 전력을 절약하면서 성능을 측정하고 개선하는 도구를 이용하라.
  3. Health Services: 센서 데이터 사용을 최적화하여 전력 효율적인 방식으로 건강 및 피트니스 앱을 쉽게 구축할 수 있다.
fornewid commented 2 years ago

Compose for Wear OS

작년부터 Jetpack Compose를 Wear OS로 가져오려고 노력하고 있다.

Jetpack Compose는 UI 개발을 단순화하고 가속화하는 데 도움이 되는 현대적인 선언형 UI 툴킷이다. 또한 이미 Wear Material Design을 준수하는 다양한 UI 구성 요소를 제공하므로 디자인 가이드라인을 더 쉽게 따를 수 있다.

Wear OS용 Compose는 Jetpack Compose와 모든 원칙과 기본 구성 요소를 공유한다. 또한 시계 UX에 최적화된 고유한 구성 요소도 있다.

현재 Wear OS용 Compose는 베타 버전! -> g.co/wear/compose

즉, 프로덕션 앱을 만드는데 사용할 수 있고, API가 Stable 임을 의미한다. 올해 하반기에 1.0 release 버전이 출시될 예정이고, 성능과 기존 구성 요소를 연마하는 데 중점을 둘 것.

오픈 소스 커뮤니티의 피드백과 참여를 통해 Compose for Wear OS를 개발해왔다. 개발자 프리뷰 이후로 Navigation, Scale LazyLists, 입력 및 제스처 지원 등과 같은 많은 구성 요소를 추가했다.

Google의 스마트워치 플랫폼용 UI를 구현할 때, Compose for Wear OS 사용을 권장한다.


Compose for Wear OS는 이미 View와 함께 사용할 수 있는 더 많은 구성 요소를 제공하며 최신 Wear OS 디자인 지침을 준수하는 사용자 환경을 만드는 데 도움이 되도록 설계되었다.

오늘은 베타 버전에 적용된 주요 변경 사항에 중점을 둔다. Compose for Wear OS의 기본 구성 요소 및 원칙에 대해 자세히 알아보려면 개발자 사이트를 방문하세요.

d.android.com/wear


swipe-to-dismiss 제스처를 지원하는 Navigation composable을 제공한다. 개념은 Mobile과 비슷해서 Compose 지식을 그대로 적용할 수 있다.

val navController = rememberSwipeDismissableNavController()

SwipeDismissableNavHost(
    navController = navController,
    startDestination = Screen.MainScreen.route
) {
    composable(route = Screen.MainScreen.route) {
        MyListScreen( ... )
    }
    composable(route = Screen.DestailsScreen.route + "/{$ID}", ...) {
        MyDetailScreen( ... )
    }
}

ScalingLazyColumn은 스크롤할 때 가장자리의 항목이 축소되고 투명해지는 컴포넌트.

ScalingLazyColumn(
    autoCentering = AutoCenteringParams() // default value
) {
    item {
        ListHeader { Text("Title") }
    }
    items(20) {
        Chip(
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}

AutoCentering: 첫 번째 항목과 마지막 항목을 포함한 모든 항목이 스크롤되어 뷰포트 중앙에 표시된다.

ScalingLazyListAnchorType:

항목의 중심 또는 가장자리가 뷰포트 중심선에 정렬되어야 하는지 여부를 제어한다.

ItemStart ItemCenter
val state = rememberScalingLazyListState()
ScalingLazyColumn(
    state = state,
    flingBehavior = ScalingLazyColumnDefaults
        .snapFlingBehavior(
            state = state,
            snapOffset = 0.dp, // default
            decay = exponentialDecay()
        )
) { item { ... } }

Fling 동작을 커스터마이징 할 수도 있다.


Picker를 사용하면 스크롤되는 목록에서 항목을 선택할 수 있다. 기본적으로 선택가능한 목록은 회전하는 실린더의 느낌을 주기 위해 양방향으로 무한 반복된다.

Picker(
    state = rememberPickerState(
        initialNumberOfOptions = 12,
        initiallySelectedOption = 5,
        repeatItems = false
    ),
    modifier = Modifier.size(64.dp, 100.dp),
    option = { hour: Int -> Option(0, "%2d".format(hour + 1)) },
    flingBehavior = PickerDefaults.flingBehavior(state),
    readOnly = selectedColumn != 0,
    readOnlyLabel = { Text("PickerLabel") }
)

ScalingLazyColumn과 유사하게 Picker에는 flingBehavior 매개변수가 있으며 기본값은 스크롤할 때 가장 가까운 옵션으로 스냅된다.

또한 여러 Picker가 있는 화면에서 한 번에 하나의 Picker만 편집할 수 있도록 ReadOnly 모드를 추가했다. Picker가 ReadOnly 모드인 경우 현재 선택한 옵션과 레이블(제공된 경우)만 표시한다.


InlineSlider를 사용하면 값 범위에서 선택할 수 있다. 주로 볼륨이나 밝기와 같은 설정을 조정하는데 적합하다.

var value by remember { mutableStateOf(2f) }

InlineSlider(
    value = value,
    onValueChange = { value = it },
    valueRange = 1f..4f,
    segmented = true,
    steps = 7,
    increaseIcon = { Icon(...) },
    decreaseIcon = { Icon(...) }
)

Stepper는 사용자가 값 범위에서 선택할 수 있도록 하는 전체 화면 제어 구성 요소입니다. 예를 들어, 헤드폰의 볼륨을 제어할 때 가운데 슬롯에 텍스트가 있어야 한다.

@Composable
fun StepperScreen(
    displayValue: Int,
    onValueChange: (Int) -> Unit
) {
    Stepper(
        value = displayValue,
        onValueChange = onValueChange,
        valueProgression = 1..10
    ) { Text("Value: $displayValue") } // show the current steps
}

Dialog는 전체 화면 대화 상자를 표시하며 다른 콘텐츠 위에 겹쳐진다. 경고 또는 확인 메시지로 예상되는 단일 슬롯이 필요하고, swipe-to-dismiss를 지원한다.

Box {
    var showDialog by remember { mutableStateOf(false) }
    // launches the Alert Dialog by setting the value of showDialog
    Chip(
        onClick = { showDialog = true },
        label = { Text("Show dialog") },
    )
    if (showDialog) {
        Dialog(onDismissRequest = { showDialog = false }) {
            Alert(...) // alert details
        }
    }
}

CircularProgressIndicator는 원형으로 진행 상황을 표시하는 데 사용된다.

CircularProgressIndicator() // infinite progress indicator

CircularProgressIndicator(
    modifier = Modifier.fillMaxSize().padding(all = 1.dp),
    progress = 0.3f,
    strokeWidth = 5.dp,
    startAngle = 295.5f,
    endAngle = 245.5f
)

CircularProgressIndicator를 사용하는 방법에는 몇 가지 옵션이 있다.

var progress by remember { mutableStateOf(0.1f) }
val animatedProgress by animateFloatAsState(
    targetValue = progress,
    animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
)
Column(horizontalAlignment = Alignment.CenterHorizontally) {
    CircularProgressIndicator(
        progress = animatedProgress
    )
    CompactChip(
        modifier = Modifier.width(90.dp),
        onChip = { if (progress < 1f) progress += 0.1f },
    )
}

Android Studio Electric Eel을 사용하면, Compose for Wear OS로 개발할 때 자동완성이나 Live Edit 등 다양한 기능들을 사용할 수 있다. Wear OS를 시작할 때 도움되도록 Wear OS용 Compose 새 프로젝트 템플릿을 추가했다.

Composable Preview for Wear OS

import androidx.compose.ui.tooling.preview

@Preview(
    apiLevel = 26,
    uiMode = Configuration.UI_MODE_TYPE_WATCH,
    showSystemUi = true,
    device = Devices.WEAR_OS_LARGE_ROUND
)
@Composable
fun PreviewCustomComposable() {
    CustomComposable(...)
}

Live Edit: https://youtu.be/jpUVamtoKOs?t=851

코드를 다시 컴파일하거나 앱을 설치할 필요가 없다. Live Edit는 편집기에서 변경 사항을 적용할 때 빠른 피드백을 제공하고 미리보기 창이나 장치의 앱에 UI를 즉시 반영한다.



github.com/google/horologist

Wear OS용 Compose에서 제공하는 기능을 확장하는 Wear 라이브러리 세트를 제공하는 Google 오픈 소스 프로젝트.

fornewid commented 2 years ago

Wear Performance

Making your app snappy

시계는 휴대전화보다 센서가 더 많지만 배터리는 훨씬 작다. 따라서 시작부터 성능에 초점을 맞추는 것이 중요하다.

성능 테스트를 일상적인 개발 흐름과 통합하는 것이 좋다. 이렇게 하면 Play 스토어에 게시하기 전에 문제를 식별하는 데 도움이 되므로, 최종 사용자와 관련된 성능 문제를 제거하는데 들어가는 전체 소요 시간을 줄일 수 있다.

지금부터 앱 성능을 개선하는 데 도움이 되는 몇 가지 간단한 팁을 소개한다.

릴리스 빌드로만 성능을 측정하라.

JankStats 라이브러리를 설치하여 앱을 시작하면 프레임 시간을 확인할 수 있고, 앱 내부 테스트 및 빌드에서 chunky 동작에 대한 세부 정보를 수집할 수 있다.

콜백을 구현하고, Jank 프레임을 로깅하는 예제 코드.

앱 시작 시간을 측정하기 위해 Macobenchmark 라이브러리를 설정한다.

Macrobenchmark는 최초 실행의 콜드 스타트부터 완전히 최적화된 후 웜 스타트까지 다양한 시나리오에서 앱 시작을 정확하게 측정한다.

시작 프로파일링 및 프레임 타이밍에 대한 예제를 보려면 Android Performance 샘플을 참고할 것.

이것은 추가 작업이 필요하지 않다.

사용자가 Play 스토어에서 앱을 다운로드하면 기준 프로필이 시작되어 Compose for Wear OS 및 기타 여러 Jetpack 라이브러리와 같은 라이브러리를 자동으로 최적화한다. 이렇게 하면 시작 성능이 향상되고 앱이 Play 스토어에서 다운로드될 때 버벅거림이 줄어든다.

Macrobenchmark를 사용하여 로컬에서 테스트하여 효과를 측정하거나 앱에 대한 Baseline Profiles 규칙을 생성하여 성능을 더욱 향상시킬 수 있다.

항상 오프라인 사용을 잘 처리할 수 있도록 앱을 만들어라. 네트워크가 연결되지 않은 경우에도 잘 작동해야 한다.

LTE만 사용할 수 있는 경우에는, 모든 화면에서 콘텐츠를 새로 고치거나 사용자가 목록을 스크롤할 때 단일 이미지를 로드하는데 LTE를 사용하지 마십시오. 빠른 Wi-Fi가 연결되어 있고 시계가 충전 중일 때, 나중에 필요할 수 있는 이미지를 미리 가져와 캐시해 보십시오.

대부분의 네트워크 사용 최적화는 WorkManager 같은 Android 프레임워크를 사용하여 쉽게 수행할 수 있다. 새로 고침 작업을 즉시 실행하는 대신 적절한 빈도로 적절한 조건이 충족될 때 실행되도록 예약하면 된다.

Health Services는 건강 데이터를 효율적으로 수집할 수 있다.

fornewid commented 2 years ago

Health Services

Power-efficient health and fitness apps

스마트워치는 수백만 명의 사람들이 건강과 피트니스 관리에 보다 적극적인 역할을 할 수 있도록 지원한다. Wear OS에서는 개발자가 이러한 사용자를 위한 훌륭한 경험을 구축할 수 있도록 돕는 것이 핵심이다.

그리고 Health Services를 이용하면 Wear OS 시계에서 생성된 센서 데이터를 활용하는 전력 효율적인 앱을 훨씬 쉽게 구축할 수 있다. 작년에 우리는 알파로 Health Services를 출시했고, 올해는 API가 곧 베타 버전으로 출시될 예정이다.

Health Services를 개선하기 위해 작년에 수많은 앱 개발자와 광범위하게 협력했다.

개발자는 Health Services를 사용하여 실시간 센서 데이터를 수집한 다음, 해당 데이터를 사용자 휴대폰의 Health Connect에 저장할 수 있다. 사용자 권한이 있는 앱은 이 데이터 저장소에 액세스하고 서로 동기화할 수 있다.

이 세션에서는 배터리 수명, 개발자 경험, 미래 보장이라는 세 가지에 초점을 맞추고 싶다.

먼저 배터리 수명을 살펴본다.

건강 및 피트니스 추적을 위해서 이상적으로는 여러 날에 걸쳐 운동, 일일 활동 및 수면과 같은 항목을 측정하기 위해 높은 빈도로 센서가 항상 켜져 있어야 한다.

구형 스마트워치에서 이러한 센서와 알고리즘은 주요 애플리케이션 프로세서의 각 앱에서 관리했으며, 이는 심박수와 같은 데이터를 처리해야 할 때마다 깨어난다.

이 접근 방식은 배터리 수명에 큰 영향을 미쳤다.

Health Services를 통해 앱은 최신 스마트워치 아키텍처를 활용할 수 있고, 이 아키텍처에서는 훨씬 더 많은 데이터 수집 및 처리를 저전력 프로세서로 내릴 수 있으므로 장기간 동안 애플리케이션 프로세서를 일시 중단할 수 있다.

이는 Health Services가 다른 API보다 훨씬 적은 전력을 소비하면서도 여전히 빈도가 높은 데이터를 제공할 수 있음을 의미한다.

다음으로 개발자 경험에 대해 몇 가지 얘기하고 싶다.

Health Services를 사용하면 기본 하드웨어의 모든 차이점에 우아하게 적응하는 경험을 통해 앱을 한 번만 작성할 수 있다. 베타 릴리스에서는 건강 및 피트니스 경험의 핵심 사용 사례에 해당되는 세 가지 클라이언트를 제공한다.

그 중 하나인 ExerciseClient를 사용하여 운동을 시작하는 예제 코드. 위치, 속도 및 심박수, 평균 속도, 전체 거리와 같은 메트릭을 계산할 수 있다.

운동을 시작한 후 업데이트를 수신하는 UpdateListener를 만드는 예제 코드. 활성 또는 일시 중지와 같은 데이터 및 운동 상태도 Health Services에서 관리한다.

마지막으로 미래 보장에 대해서. 스마트워치 기술은 빠르게 발전하고 있고, 매년 이러한 장치에 새로운 센서와 더 나은 알고리즘이 탑재된다.

Health Services는 이러한 변경이 이루어짐에 따라 성장하도록 구축되어 앱이 Wear 기기 전반에 걸쳐 일관된 API를 통해 개선사항을 활용할 수 있도록 한다.

새로운 시계에서 새로운 센서를 사용할 수 있게 되면 API에 새로운 데이터 유형을 추가하고 해당 측정항목에 쉽게 액세스할 수 있다.

fornewid commented 1 year ago

Related Links

Compose for Wear OS

Performance

Health Services