| **Note:** This guide uses`SensorManager`for retrieving steps data. We recommend using the[Recording API on mobile](https://developer.android.com/health-and-fitness/guides/recording-api)for recording steps in a power-efficient way.

This guide walks you through building a basic mobile step counter app, which is a common foundation for many Health \& Fitness apps.

This workflow integrates the following APIs:

- [SensorManager](https://developer.android.com/guide/topics/sensors/sensors_motion)for retrieving steps data from a mobile device.
- [Room](https://developer.android.com/training/data-storage/room)for local data storage.
- [Health Connect](https://developer.android.com/health-and-fitness/guides/health-connect)for storing and sharing health and fitness data on device.

For additional support on data reading and the tools necessary, refer to[Use Android Sensor Manager to track steps from a mobile device](https://developer.android.com/health-and-fitness/guides/basic-fitness-app/read-step-count-data).

If you haven't already set up your development environment for using[Health Connect](https://developer.android.com/health-and-fitness/guides/health-connect), follow these[getting started](https://developer.android.com/health-and-fitness/guides/health-connect/develop/get-started)steps.

## Request permissions on handheld device

Before getting exercise data you must request and be granted the appropriate permissions.

As a best practice, only request the permissions you need, and make sure to[request each permission in context](https://developer.android.com/training/permissions/requesting#workflow_for_requesting_permissions), instead of requesting all permissions at once when the user starts the app.

The[step counter sensor](https://developer.android.com/guide/topics/sensors/sensors_motion#sensors-motion-stepcounter), which many exercise apps rely on, uses the`ACTIVITY_RECOGNITION`permission. Add this permission in your AndroidManifest.xml file:  

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools">

      <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>

    </manifest>

To request the`ACTIVITY_RECOGNITION`permission at runtime refer to the[permission request documentation](https://developer.android.com/training/permissions/requesting#request-permission).

You will also need to declare a`FOREGROUND_SERVICE`in the manifest. Since you are requesting the`ACTIVITY_RECOGNITION`permission, declare`FOREGROUND_SERVICE_TYPE_HEALTH`:  

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH"/>

Visit[Foreground services](https://developer.android.com/develop/background-work/services/fgs)to learn more about foreground services and foreground service types.

## Manage UI state using a ViewModel

To properly manage the UI state, use a ViewModel.[Jetpack Compose and ViewModels](https://developer.android.com/jetpack/compose/libraries#viewmodel)offers you a more in-depth look at this workflow.

Also, use UI layering, which is a critical part for building UIs with Compose and lets you follow architecture best practices, such as[Unidirectional Data Flow](https://developer.android.com/jetpack/compose/architecture#udf). To learn more about UI layering, refer to the[UI layer documentation](https://developer.android.com/topic/architecture/ui-layer).

In this example app, the UI has three basic states:

- **Loading:**Shows a spinning circle.
- **Content:**Shows information about your steps for today.
- **Error:**Shows a message when something goes wrong.

The`ViewModel`exposes these states as a Kotlin`Flow`. Use a sealed class to contain the classes and objects that represent the possible states:  

    class TodayScreenViewModel(...) {

      val currentScreenState: MutableStateFlow<TodayScreenState> = MutableStateFlow(Loading)

      [...]

    }

    sealed class TodayScreenState {
        data object Loading : TodayScreenState()
        data class Content(val steps: Long, val dailyGoal: Long) : TodayScreenState()
        data object Error: TodayScreenState()
    }

Compose UI then collects this`Flow`as a Compose`State`and acts on it:  

    val state: TodayScreenState = todayScreenViewModel.currentScreenState.collectAsState().value