之前App中一直使用的是
Google Fit
API,今年五月的Google I/O 大会上已经宣布停止服务。所以我们需要迁移到Health Connect
。
官方文档地址:https://developer.android.com/health-and-fitness/guides/health-connect
1.迁移
Google Fit
迁移首先就是删除相关代码及依赖,主要的依赖库如下。
implementation 'com.google.android.gms:play-services-auth:20.4.1'
implementation 'com.google.android.gms:play-services-fitness:21.1.0'
如果你有谷歌登录相关功能,保留play-services-auth
。
2.接入
配置
- 添加依赖
implementation "androidx.health.connect:connect-client:1.1.0-alpha07"
Health Connect
SDK目前限制最小api支持到26(Android 8.0),所以一旦接入此功能后,需要将minSdkVersion
改为26。
如果你的应用还支持到8.0以下。可以添加以下配置覆盖此依赖库的限制:
<manifest>
<uses-sdk tools:overrideLibrary="androidx.health.connect.client"/>
...
</manifest>
另外注意此功能最小只支持到Android 9.0,所以需要判断大于等于P(28)。比如此功能的开关只有9.0及以上手机展示。
- 添加所需的权限及声明
Health Connect
可见包名:
<manifest>
<uses-permission android:name="android.permission.health.WRITE_EXERCISE"/>
<uses-permission android:name="android.permission.health.WRITE_TOTAL_CALORIES_BURNED"/>
<application>
...
</application>
<queries>
<package android:name="com.google.android.apps.healthdata" />
</queries>
</manifest>
权限根据App的情况添加,比如这里我不需要读取权限,只需要运动和卡路里的写入权限。
如需查看权限及其对应数据类型的完整列表,请参阅数据类型列表。
- 应用的隐私权政策
Android 清单需要有一个显示应用隐私权政策的承载页面,用于说明如何使用和处理用户数据。一般可以写一个Webview页面,加载对应的隐私政策链接。
...
<application>
...
<!-- For supported versions through Android 13, create an activity to show the rationale
of Health Connect permissions once users click the privacy policy link. -->
<activity
android:name=".PermissionsRationaleActivity"
android:exported="true">
<intent-filter>
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
</intent-filter>
</activity>
<!-- For versions starting Android 14, create an activity alias to show the rationale
of Health Connect permissions once users click the privacy policy link. -->
<activity-alias
android:name="ViewPermissionUsageActivity"
android:exported="true"
android:targetActivity=".PermissionsRationaleActivity"
android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
<intent-filter>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
<category android:name="android.intent.category.HEALTH_PERMISSIONS" />
</intent-filter>
</activity-alias>
...
</application>
...
显示位置如下:
处理流程
检查Health Connect
是否可用。
fun isSupported(context: Context): Boolean {
val providerPackageName = "com.google.android.apps.healthdata"
val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName)
if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
return false // sdk不可用
}
if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
// 安装healthconnect
val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
context.startActivity(
Intent(Intent.ACTION_VIEW).apply {
setPackage("com.android.vending")
data = Uri.parse(uriString)
putExtra("overlay", true)
putExtra("callerId", context.packageName)
}
)
return false
}
return true
}
上面的代码首先检测Android版本是否符合,其次是否可用。
Health Connect
作为 Android 14系统的一部分打包在一起, 直接可用。且无法从设备上卸载,用户在设置 >安全与隐私权 >隐私权里进行设置。- Android 13 或更低版本需要在Google Play 商店中下载。
权限及数据操作
在Health Connect
可用后,我们可以进行申请权限,判断权限,读写数据、
- 申请权限
private val permissions = setOf(
HealthPermission.getWritePermission(ExerciseSessionRecord::class),
HealthPermission.getWritePermission(ActiveCaloriesBurnedRecord::class),
)
private val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()
val requestPermissions = registerForActivityResult(requestPermissionActivityContract) {
granted ->
if (granted.containsAll(permissions)) {
// 成功授权
} else {
// 缺少所需的权限
}
}
// 请求权限
requestPermissions.launch(permissions)
- 检查权限
先使用getGrantedPermissions
检查权限,没有权限时做权限申请。
suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
val granted = healthConnectClient.permissionController.getGrantedPermissions()
if (granted.containsAll(permissions)) {
// 已授予的权限,可以继续执行插入或读取数据
} else {
requestPermissions.launch(PERMISSIONS)
}
}
- 写入数据
suspend fun writeExerciseSession(min: Int, calories: Double) {
try {
val end = ZonedDateTime.now().withNano(0)
val start = end.plusMinutes(-min.toLong())
healthConnectClient?.insertRecords(
listOf(
ExerciseSessionRecord(
startTime = start.toInstant(),
startZoneOffset = start.offset,
endTime = end.toInstant(),
endZoneOffset = end.offset,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_STRENGTH_TRAINING,
title = "Workout"
),
TotalCaloriesBurnedRecord(
startTime = start.toInstant(),
startZoneOffset = start.offset,
endTime = end.toInstant(),
endZoneOffset = end.offset,
energy = Energy.calories(calories)
)
)
)
} catch (e: Exception) {
// Run error handling here
}
}
这里简单演示了写入时长卡路里数据,其他类型数据操作方法可以参考官方文档。可以根据项目实际需求使用,这里就不赘述了。
另外注意:
- 有30 天读取限制,也就是说你可以读取首次授予任何权限前最多 30 天的数据。
- 上架前声明对 Health Connect 数据类型的访问权限
3.已知问题记录
三星健康
Health Connect
让健康与健身应用在统一生态系统中存储和共享设备上的相同数据。所以除了常用的Google Fit外,三星健康也是可以读取其中的数据。
但是在测试的过程中发现三星健康中并不会读取显示。三星健康设置中也没有对应的Health Connect
选项,即使我在Health Connect
的管理页中发现了三星健康,并授予了全部权限。
经过后面的查找相关问题,发现在国行版本的三星健康上未开放此功能,据说可以使用国外SIM卡进行解锁(此方法未验证)。
检查是否已安装 Health Connect
Android 14以下手机需要安装Health Connect
,没有安装时会跳转应用市场引导下载。这里注意对跳转方法做异常处理。否则会有ActivityNotFoundException
异常。比如部分机型(华为)。
No Activity found to handle Intent {
act=android.intent.action.VIEW dat=market://details?id=com.google.android.apps.healthdata&url=healthconnect://onboarding pkg=com.android.vending (has extras) }
RemoteException
Android 14以下手机因为安装了Health Connect
,所以此APP一旦被杀死,服务停止,就无法正常使用。例如我们判断权限是否授权的方法getGrantedPermissions
。
报错信息:
android.os.RemoteException:Binding to service failed
androidx.health.connect.client.impl.HealthConnectClientImpl.getGrantedPermissions(SourceFile:23)
Caused by:
android.os.RemoteException:Binding to service failed
androidx.health.platform.client.impl.ipc.internal.ServiceConnection.connect(SourceFile:11)
androidx.health.platform.client.impl.ipc.internal.ServiceConnection.enqueue(SourceFile:4)
androidx.health.platform.client.impl.ipc.internal.ConnectionManager.handleMessage(SourceFile:27)
android.os.Handler.dispatchMessage(Handler.java:106)
android.os.Looper.loop(Looper.java:219)
android.os.HandlerThread.run(HandlerThread.java:67)
处理方法还是捕获一下异常,同时也可以提示用户启动Health Connect
。打开应用后台自启动等开关。
总结
总体接入难度不高,只是会踩点小坑。记录分享出来,帮助有需要的人。