アイリッジ開発者ブログ

アイリッジに所属するエンジニアが技術情報を発信していきます。

Google Fitと連携して歩数を取得する

開発部第2グループの天野です。 AndroidアプリにGoogle Fitと連携して歩数取得する方法を調べたので実装方法をご紹介します。

はじめに

基本的に以下の手順で可能です。

Get started on Android | Google Fit | Google Developers

ただ、その中で特に実装前の準備が難しかったため、案件で組み込んだときの手順や注意事項をメモしておきます。何か参考になれば。

調査時に実装したコードも抜粋してサンプルとして載せておきますが、コードは公式やGitHubに転がっているので、そちらを読んでもらっても良いと思います。

前提

  • Firebaseでプロジェクトが作成されている
  • Googleアカウントの認証はFirebase Authenticationを使用する
  • Google FItアプリを端末にインストール済

注意

  • OAuth同意画面の審査が4〜6週間かかるので、公開ステータスを公開に変更する場合は余裕を持って行う
  • OAuth ユーザー数の上限(一日に連携を開始できるユーザー数の上限)が設定されているので、既存アプリにGoogle Fit連携を追加する場合は期待できるユーザー数に応じて上限緩和申請が必要
  • OAuthのスコープで権限を広くしてしまうと審査が通りづらくなるらしいので、必要な権限を適切に指定する ex)読み込みだけでいいのに、書き込みも要求する。歩数の取得だけでいいのに身体情報の読み込みも要求する

準備

GCP

Fitness APIを有効化する

  1. APIとサービスのダッシュボードにあるAPIとサービスの有効化を押下

    f:id:iridge-tech:20220105150540p:plain

  2. Fitness APIを検索・選択し、有効化にする を押下 f:id:iridge-tech:20220105150857p:plain

  3. APIとサービスのダッシュボードにFitness APIが表示されていれば有効化完了

    f:id:iridge-tech:20220105150820p:plain

OAuth同意画面を設定する

  1. APIとサービスのOAuth同意画面で、外部を選択して作成を押下

    f:id:iridge-tech:20220105150932p:plain

  2. アプリ情報、アプリのドメイン、デベロッパーの連絡先情報の必須情報を入力して保存して次へを押下

    f:id:iridge-tech:20220105150947p:plain

  3. スコープを追加または削除 を押下し、スコープに.../auth/fitness.activity.readを追加して更新を押下

    f:id:iridge-tech:20220105151005p:plain

  4. テストユーザーを追加し、保存して次へを押下

    f:id:iridge-tech:20220105151022p:plain

Firebase

Google Authenticationの設定

  1. Authentication画面でGoogleを選択。有効にし保存を押下

    f:id:iridge-tech:20220105151037p:plain

フィンガープリントの設定

  1. プロジェクトの設定画面で対象アプリを選択し、フィンガープリントを追加を押下

    f:id:iridge-tech:20220105151051p:plain

  2. google-services.jsonをダウンロードし、Android Studioで組み込み

実装サンプル

Kotlinでの実装サンプルです。

  • Gradle(appモジュール)にFitnessとAuthenticationを追加
dependencies {
        implementation("com.google.android.gms:play-services-fitness:20.0.0")
        implementation("com.google.android.gms:play-services-auth:19.2.0")
}
  • Google Fitのインストール確認
fun checkIfFitInstalled(context: Context): Boolean {
    return try {
        context.packageManager.getPackageInfo("com.google.android.apps.fitness", PackageManager.GET_ACTIVITIES)
        true
    } catch (e: Exception) {
        false
    }
}
  • パーミッション取得
fun checkGoogleSignInFitnessPermission(activity: Activity): Boolean {
    val fitnessOptions = FitnessOptions.builder()
        .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
        .build()
    val account = GoogleSignIn.getAccountForExtension(activity, fitnessOptions)
    return if (GoogleSignIn.hasPermissions(account, fitnessOptions)) {
        true
    } else {
        GoogleSignIn.requestPermissions(activity, PERMISSION_GOOGLE_ACCOUNT_SIGN_IN, account, fitnessOptions)
        false
    }
}
  • 指定期間の歩数取得
fun getStepCount(activity: Activity, startDate: Date, endDate: Date, listener: OnReadStepCount) {
    val request = DataReadRequest.Builder()
        .aggregate(DataType.TYPE_STEP_COUNT_DELTA)
        .bucketByTime(1, TimeUnit.HOURS)
        .setTimeRange(startDate.time, endDate.time, TimeUnit.MILLISECONDS)
        .build()

    val fitnessOptions = FitnessOptions.builder()
        .addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
        .build()

    val account = GoogleSignIn.getAccountForExtension(activity, fitnessOptions)

    if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
        listener.invoke(null)
    } else {
        Fitness.getHistoryClient(activity, account)
            .readData(request)
            .addOnSuccessListener{ response ->
                                val stepCount = response.buckets
                    .flatMap{it.dataSets}
                                        .flatMap{it.dataPoints}
                                        .sumBy{it.getValue(Field.FIELD_STEPS).asInt()}
                                listener.invoke(stepCount)
                        }
                        .addOnFailureListener{
                                Timber.e(it)
                listener.invoke(null)
                        }
        }
}