Android

[Android] Google Fitness API

이예짜니 2021. 5. 30. 01:55

개요

Google Fitness API는 사용자의 건강 및 활동(운동) 정보를 기록하고 관리하는 것을 서비스입니다.

모바일 앱을 통해 사용 가능하며, 반드시 구글 계정을 연동해야합니다.

기록되는 데이터는 클라우드 공간(Google Fitness Store)에 저장되며, 다른 기기(기존에 연동한 계정이면)에서도 값을 확인할 수 있습니다.


권한

사용자의 신체 활동 정보에 엑세스하는 권한

Android 10 (API level 29) 이상부터는 권한 동의 필요 (이하는 권한 자동으로 부여)

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

라이브러리

build.gradle에서 Google Play Service Client 라이브러리 추가

plugin {
    id("com.android.application")
}

implementation 'com.google.android.gms:play-services-fitness:20.0.0'
implementation 'com.google.android.gms:play-services-auth:19.0.0'

OAuth client ID 발급

  1. [구글 클라우드 플랫폼](https://console.cloud.google.com/) 에서 프로젝트를 생성한다
  2. Fitness API 사용 설정
  3. OAuth 동의 화면 구성
  4. OAuth client ID 발급 (이름, 패키지 이름, SHA-1 인증서 디지털 지문 등록)

SHA-1 인증서 디지털 지문 조회 방법

Terminal 창에서 아래 명령어 입력하면 인증서 정보 나옴

keytool -list -v -keystore "키 경로 지정"(예시 ~/.android/debug.keystore) -alias androiddebugkey -storepass android -keypass android

테스트 시 debug 인증서 정보 사용하고,

배포 시 realse 인증서 정보의 지문으로 변경해야함

 

테스트 시 실행 과정

1. Api level 29 이상이면 권한(신체 활동 정보에 대한)을 받는다

 

2. 조회하고자 하는 데이터 타입 설정

val fitnessOptions: FitnessOptions = FitnessOptions.builder()
    .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE)
    .addDataType(DataType.TYPE_STEP_COUNT_DELTA)
    .addDataType(DataType.TYPE_CALORIES_EXPENDED)
    .addDataType(DataType.TYPE_DISTANCE_DELTA)
    .addDataType(DataType.TYPE_MOVE_MINUTES)
    .addDataType(DataType.TYPE_HEIGHT)
    .addDataType(DataType.TYPE_WEIGHT)
    .build()

 

3. Google OAuth 권한을 받는다

GoogleSignIn.requestPermissions(
    requireActivity(),
    FITNESS_CODE,
    getGoogleAccount(), fitnessOptions
)​

OAuth client ID를 제대로 발급 받았다면 구글 로그인 페이지 후 OAuth 권한 요청 페이지로 이동 할 것이다

 

4. Fitness 데이터 조회

데이터 조회는 Fitness.getHistoryClient()를 사용하며 DataReadRequest.Builder()를 통해 읽고자 하는 데이터의 타입 및 기간을 미리 지정한다.
아래의 메서드는 조회하고자 하는 기간(단위 milliseconds)을 입력하면 걸음 수, 이동 거리, 이동 시간, 소모된 칼로리를 조회하는 예시이다.

// 걸음 수 조회 예시
private fun readSteps(startTime: Long, endTime: Long) {
    val dataSource = DataSource.Builder()
        .setAppPackageName("com.google.android.gms")
        .setDataType(DataType.TYPE_STEP_COUNT_DELTA)
        .setType(DataSource.TYPE_DERIVED)
        .setStreamName("estimated_steps")
        .build()
  
    val request = DataReadRequest.Builder()
        .aggregate(dataSource)
        .bucketByTime(1, TimeUnit.DAYS)
        .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
        .build()
  
    Fitness.getHistoryClient(context, getGoogleAccount())
        .readData(request)
        .addOnSuccessListener { response ->
            response.buckets.map { bucket ->
                val dataSetStep = bucket.getDataSet(DataType.TYPE_STEP_COUNT_DELTA)

                dataSetStep?.let {
                    var dailyStep = 0
                    it.dataPoints.map { dataPoint ->
                        dailyStep += dataPoint.getValue(Field.FIELD_STEPS).asInt()
                    }
                    Logger.d("Daily step: $dailyStep")
                }
            }
        }
        .addOnFailureListener { e ->
            Logger.d("There was a problem getting the step count.", e)
        }
}​

 

// 이동 거리, 이동 시간, 소모된 칼로리 조회 예시
private fun readTimeDistanceCalories(startTime: Long, endTime: Long) {
    val request = DataReadRequest.Builder()
        .read(DataType.TYPE_DISTANCE_DELTA)
        .read(DataType.TYPE_MOVE_MINUTES)
        .read(DataType.AGGREGATE_CALORIES_EXPENDED)
        .bucketByTime(1, TimeUnit.DAYS)
        .setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
        .build()
  
    Fitness.getHistoryClient(context, getGoogleAccount())
        .readData(request)
        .addOnSuccessListener { response ->
            response.buckets.map { bucket ->
                val dataSetDistance = bucket.getDataSet(DataType.TYPE_DISTANCE_DELTA)
                val dataSetMoveMinutes = bucket.getDataSet(DataType.TYPE_MOVE_MINUTES)
                val dataSetCalories = bucket.getDataSet(DataType.AGGREGATE_CALORIES_EXPENDED)
                var dailyDistance = 0.0
                var dailyCalories = 0.0

                dataSetDistance?.let {
                    it.dataPoints.map { dataPoint ->
                        dailyDistance += dataPoint.getValue(Field.FIELD_DISTANCE).asFloat()
                    }
                    Logger.d("Daily distance: $dailyDistance")
                }
                dataSetMoveMinutes?.let {
                    Logger.d("Daily time: ${it.dataPoints.size}")
                }
                dataSetCalories?.let {
                    if (dailyDistance != 0.0) {
                        it.dataPoints.map { dataPoint ->
                            dailyCalories += dataPoint.getValue(Field.FIELD_CALORIES).asFloat()
                        }
                    }
                    Logger.d("Daily Calories: $dailyCalories")
                }
            }
        }
}​

 

 

5. 테스트 결과

  Google Fitness App 위에서 구현한 Test App 특이 사항
걸음 수 4413 4413 -
이동 거리 2.39 km 2925 meter -
이동 시간 59 min 59 min -
칼로리 1810 Cal 1810 Cal 오늘 기준 23:59:59 아닌
현재 시간 기준으로 계산해야함
(Google Fitness App은 30초 단위로 칼로리 계산)

위에서 테스트한 API 외에도 영양정보, 물 섭취량, 수면기록도 관리할 수 있다.

 

 

 

참고

https://developers.google.com/fit/android