이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Build a basic fitness app\n\n| **Note:** This guide uses `SensorManager` for retrieving steps data. We recommend using the [Recording API on mobile](/health-and-fitness/guides/recording-api) for recording steps in a power-efficient way.\n\nThis guide walks you through building a basic mobile step counter app, which\nis a common foundation for many Health \\& Fitness apps.\n\nThis workflow integrates the following APIs:\n\n- [SensorManager](/guide/topics/sensors/sensors_motion) for retrieving steps data from a mobile device.\n- [Room](/training/data-storage/room) for local data storage.\n- [Health Connect](/health-and-fitness/guides/health-connect) for storing and sharing health and fitness data on device.\n\nFor additional support on data reading and the tools necessary, refer to [Use\nAndroid Sensor Manager to track steps from a mobile device](/health-and-fitness/guides/basic-fitness-app/read-step-count-data).\n\nIf you haven't already set up your development environment for using\n[Health Connect](/health-and-fitness/guides/health-connect), follow these\n[getting started](/health-and-fitness/guides/health-connect/develop/get-started)\nsteps.\n\nRequest permissions on handheld device\n--------------------------------------\n\nBefore getting exercise data you must request and be granted the appropriate\npermissions.\n\nAs a best practice, only request the permissions you need, and make sure to\n[request each permission in context](/training/permissions/requesting#workflow_for_requesting_permissions), instead of requesting all\npermissions at once when the user starts the app.\n\nThe [step counter sensor](/guide/topics/sensors/sensors_motion#sensors-motion-stepcounter), which many exercise apps rely on, uses the\n`ACTIVITY_RECOGNITION` permission. Add this permission in your AndroidManifest.xml\nfile: \n\n \u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n \u003cmanifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/tools\"\u003e\n\n \u003cuses-permission android:name=\"android.permission.ACTIVITY_RECOGNITION\"/\u003e\n\n \u003c/manifest\u003e\n\nTo request the `ACTIVITY_RECOGNITION` permission at runtime refer to the\n[permission request documentation](/training/permissions/requesting#request-permission).\n\nYou will also need to declare a `FOREGROUND_SERVICE` in the manifest. Since you\nare requesting the `ACTIVITY_RECOGNITION` permission, declare\n`FOREGROUND_SERVICE_TYPE_HEALTH`: \n\n \u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/\u003e\n \u003cuses-permission android:name=\"android.permission.FOREGROUND_SERVICE_HEALTH\"/\u003e\n\nVisit [Foreground services](/develop/background-work/services/fgs)\nto learn more about foreground services and foreground service types.\n\nManage UI state using a ViewModel\n---------------------------------\n\nTo properly manage the UI state, use a ViewModel.\n[Jetpack Compose and ViewModels](/jetpack/compose/libraries#viewmodel) offers you a more in-depth look at this\nworkflow.\n\nAlso, use UI layering, which is a critical part for building UIs with Compose\nand lets you follow architecture best practices, such as\n[Unidirectional Data Flow](/jetpack/compose/architecture#udf). To learn more about UI layering, refer to the\n[UI layer documentation](/topic/architecture/ui-layer).\n\nIn this example app, the UI has three basic states:\n\n- **Loading:** Shows a spinning circle.\n- **Content:** Shows information about your steps for today.\n- **Error:** Shows a message when something goes wrong.\n\nThe `ViewModel` exposes these states as a Kotlin `Flow`. Use a sealed class to\ncontain the classes and objects that represent the possible states: \n\n class TodayScreenViewModel(...) {\n\n val currentScreenState: MutableStateFlow\u003cTodayScreenState\u003e = MutableStateFlow(Loading)\n\n [...]\n\n }\n\n sealed class TodayScreenState {\n data object Loading : TodayScreenState()\n data class Content(val steps: Long, val dailyGoal: Long) : TodayScreenState()\n data object Error: TodayScreenState()\n }\n\nCompose UI then collects this `Flow` as a Compose `State` and acts on it: \n\n val state: TodayScreenState = todayScreenViewModel.currentScreenState.collectAsState().value"]]