You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Health Connect读取运动GPS轨迹?Kotlin开发疑难

从Health Connect获取GPS轨迹数据的问题

问题背景

我正在Android Studio中开发Kotlin项目,需要从Health Connect获取GPS轨迹的经纬度数据,用来生成运动的「最快时段」列表。已经把Fitbit步行数据同步到了Health Connect,但目前卡在获取经纬度这一步。

已实现的代码

我已经能读取过去一个月的所有ExerciseSessionRecord:

val request = ReadRecordsRequest(
    recordType = ExerciseSessionRecord::class,
    timeRangeFilter = TimeRangeFilter.between(from, to)
)
val response = healthConnectClient.readRecords(request)

遇到的核心问题

  • Health Connect提供的Record类型里没有LocationRecord,现有的类型包括CervicalMucusRecord、SexualActivityRecord等
  • ExerciseSessionRecord的结构里不包含经纬度信息,其结构如下:
ExerciseSessionRecord(
    startTime: Instant,
    startZoneOffset: ZoneOffset?,
    endTime: Instant,
    endZoneOffset: ZoneOffset?,
    exerciseType: Int,
    title: String?,
    notes: String?,
    metadata: Metadata
)

测试代码及日志

MainActivity代码

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val permissionsLauncher = PermissionController.createRequestPermissionResultContract()
        val permissions = setOf(
            HealthPermission.getReadPermission(ExerciseSessionRecord::class)
        )
        var sessionsList: MutableState<List<ExerciseSessionRecord>> = mutableStateOf(listOf())


        // Catch the result from the system's permissions dialog
        val requestPermissions =
            registerForActivityResult(permissionsLauncher) { granted ->
                if (granted.containsAll(permissions)) {
                    // Permissions successfully granted
                    // PERMISSIONS: Set<string> as of Alpha11
                    Log.d(TAG, "MainActivity: Permissions granted: $granted")
                    syncJob.cancel(CancellationException("Permissions have changed. Try again."))
                } else {
                    Log.d(TAG, "MainActivity: Lack of permissions")
                }
            }

        // Check for permissions
        suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
            // For alpha09 and lower versions, use getGrantedPermissions(PERMISSIONS) instead
            val granted = healthConnectClient.permissionController.getGrantedPermissions()
            if (granted.containsAll(permissions)) {
                // Permissions already granted; proceed with inserting or reading data.
                Log.d(TAG, "MainActivity: Permissions have already been granted")
                val now = Instant.now()
                val request = ReadRecordsRequest(
                    recordType = ExerciseSessionRecord::class,
                    timeRangeFilter = TimeRangeFilter.between(now.minusSeconds(2592000), now)
                )
                val response = healthConnectClient.readRecords(request)
                sessionsList.value = response.records
            } else {
                // Launch system dialog to select permissions
                requestPermissions.launch(permissions)
            }
        }

        // Health Connect Button
        buttonHealthConnect.setOnClickListener(View.OnClickListener {
            progressBarFragment.visibility = View.VISIBLE
            initSyncJob()

            val context = this
            CoroutineScope(IO + syncJob).launch {
                delay(2000)
                if(isSDKAvailable()) {
                    val healthConnectClient = HealthConnectClient.getOrCreate(context)
                    checkPermissionsAndRun(healthConnectClient)

                    var result = ""
                    var type = ""
                    for(value in sessionsList.value){
                        Log.d(TAG, "MainActivity type = ${value.exerciseType}")
                        type = when (value.exerciseType) {
                            8 -> "Cycling"
                            79 -> "Walking"
                            else -> "Other"
                        }
                        result = result.plus("${type}: ${value.startTime}\n")
                    }
                    textViewResults.setText(result)
                    Log.d(TAG, "MainActivity: \nReturned data from Health Connect: \n$result")
                    syncJob.complete()
                } else {
                    syncJob.cancel(CancellationException("Cancelled: SDK unavailable"))
                }
            }
        })
    }

AndroidManifest代码

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

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FitnessAppsTest"
        tools:targetApi="31">

        <activity
            android:name="com.fitnessappstest.ui.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <!-- Required to specify which Health Connect permissions the app can request -->
    <uses-permission android:name="android.permission.health.READ_EXERCISE" />

    <queries>
        <!-- Declare Health Connect visibility -->
        <package android:name="com.google.android.apps.healthdata" />
    </queries>

</manifest>

Logcat输出

[-- Clicked Health Connect Button --]
MainActivity: SDK is available
MainActivity: 
    Returned data from Health Connect: 
MainActivity: syncJob complete
[-- Approved permissions in permissionLauncher --]
Permissions granted: [android.permission.health.READ_EXERCISE]


MainActivity: SDK is available
MainActivity: Permissions have already been granted
MainActivity type = 8
MainActivity type = 8
MainActivity type = 79
MainActivity type = 79
MainActivity: 
    Returned data from Health Connect: 
    Cycling: 2023-05-12T23:53:15.670Z
    Cycling: 2023-05-18T01:30:27.710Z
    Walking: 2023-06-09T04:30:50.131Z
    Walking: 2023-06-09T04:33:37.100Z
MainActivity: syncJob complete

补充说明

选择Health Connect的原因:

  • Google Fitness API将于2024年停用
  • Samsung Health API不再审核新应用
  • Garmin Connect需要审核,暂未深入了解

内容的提问来源于stack exchange,提问作者beebopbogo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:57:23