基本的なフィットネス アプリを作成する

このガイドでは、多くの健康 &フィットネス アプリの一般的な基盤である基本的なモバイル歩数計アプリの作成について説明します。

このワークフローには、次の API が統合されています。

  • SensorManager: モバイル デバイスから歩数データを取得します。
  • ローカルデータ ストレージ用の Room
  • ヘルスコネクト: 健康とフィットネスに関するデータをデバイスに保存、共有します。

データの読み取りと必要なツールに関するその他のサポートについては、Android センサー マネージャーを使用してモバイル デバイスから歩数をトラッキングするをご覧ください。

ヘルスコネクトを使用するための開発環境をまだ設定していない場合は、こちらのスタートガイドの手順に沿って設定してください。

ハンドヘルド デバイスで権限をリクエストする

エクササイズ データを取得するには、適切な権限をリクエストして、その権限を付与してもらう必要があります。

ユーザーがアプリを起動したときにすべての権限を一度にリクエストするのではなく、必要な権限のみをリクエストし、状況に応じて各権限をリクエストすることをおすすめします。

多くのエクササイズ アプリが依存する歩数カウンタ センサーは、ACTIVITY_RECOGNITION 権限を使用します。この権限を AndroidManifest.xml ファイルに追加します。

<?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>

実行時に ACTIVITY_RECOGNITION 権限をリクエストするには、権限リクエストのドキュメントをご覧ください。

また、マニフェストで FOREGROUND_SERVICE を宣言する必要もあります。ここでは ACTIVITY_RECOGNITION 権限をリクエストしているため、FOREGROUND_SERVICE_TYPE_HEALTH を宣言します。

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

フォアグラウンド サービスとフォアグラウンド サービスのタイプについて詳しくは、フォアグラウンド サービスをご覧ください。

ViewModel を使用して UI 状態を管理する

UI の状態を適切に管理するには、ViewModel を使用します。このワークフローの詳細については、Jetpack Compose と ViewModel をご覧ください。

また、UI レイヤリングを使用します。これは Compose で UI を作成するうえで不可欠であり、単方向データフローなどのアーキテクチャのベスト プラクティスに準拠できます。UI レイヤの詳細については、UI レイヤのドキュメントをご覧ください。

このサンプルアプリでは、UI に 3 つの基本的な状態があります。

  • 読み込み中: 回転する円が表示されます。
  • コンテンツ: 今日の歩数に関する情報を表示します。
  • エラー: エラーが発生したときにメッセージが表示されます。

ViewModel は、これらの状態を Kotlin Flow として公開します。シールクラスを使用して、取り得る状態を表すクラスとオブジェクトを格納します。

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 はこの Flow を Compose State として収集し、処理します。

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