Как прочитать GPS-трек активности из Health Connect?

Я создаю проект Kotlin в Android Studio, и у меня возникают проблемы с получением данных GPS из Health Connect. Я пошел на прогулку, синхронизировал FitBit с Health Connect, и теперь я хотел бы получить GPS-трек своей активности и использовать свое приложение для обработки данных широты и долготы в списке «самых быстрых результатов». Получение данных о широте и долготе кажется самой сложной задачей.

Вот важный момент. Он считывает все записи PracticeSessionRecords за последний месяц из облака Health Connect:

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

Есть типы записей для CervicalMucusRecord и SexualActivityRecord, но нет LocationRecord??? Вот полный список типов записей: https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/package-summary#classes .

А вот данные, содержащиеся в УпражненииSessionRecord. Опять же, никаких позиций широты и долготы:

      ExerciseSessionRecord(
    startTime: Instant,
    startZoneOffset: ZoneOffset?,
    endTime: Instant,
    endZoneOffset: ZoneOffset?,
    exerciseType: Int,
    title: String?,
    notes: String?,
    metadata: Metadata
)

И вот код, который я тестировал (вывод logcat в конце):

Основная деятельность:

      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"))
                }
            }
        })
    }

AndroidМанифест:

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

PS Почему Health Connect? Google Fitness API прекратит поддержку в 2024 году и будет переведен на Health Connect. Samsung Health API требует одобрения, но они больше не одобряют приложения. Garmin Connect также требует одобрения. Я не особо присматривался к Garmin Connect. Если одобрение возможно, возможно, это вариант...

1 ответ

Вы можете использовать этот документ в качестве справочного материала, и я думаю, что он поддерживается в Android U. См. это руководство о том, как перейти с Android T (13) на Android U (14).

Другие вопросы по тегам