إضافة مسارات التمارين الرياضية

تتيح مسارات التمارين الرياضية للمستخدمين تتبُّع مسار نظام تحديد المواقع العالمي (GPS) لممارسة التمارين المرتبطة أنشطتهم ومشاركة خرائط لتمارينهم مع تطبيقات أخرى.

ويوضّح هذا الدليل كيفية حصول التطبيقات على إذن لكتابة بيانات المسار كجزء من جلسة تمرين.

فيما يلي ملخص موجز لوظيفة القراءة والكتابة لمسارات التمرين:

  1. تنشئ التطبيقات إذن كتابة جديدًا لمسارات التمارين الرياضية.
  2. يحدث الإدراج عن طريق كتابة جلسة تدريب بحيث يكون حقل المسار هو حقله.
  3. القراءة:
    1. بالنسبة إلى مالك الجلسة، يتم الوصول إلى البيانات باستخدام قراءة الجلسة.
    2. من تطبيق تابع لجهة خارجية، من خلال مربّع حوار يسمح للمستخدم بمنح القراءة لمرة واحدة للمسار.

الأذونات

مسارات التمارين الرياضية لها إذن كتابة في وقت التشغيل (android.permission.health.WRITE_EXERCISE_ROUTE).

لإضافة إمكانية مسار التمرين إلى تطبيقك، ابدأ بطلب كتابة الأذونات لنوع معين من البيانات.

طلب الحصول على إذن Android 14

طلب الحصول على إذن Android 14

طلب الحصول على إذن Android 13

طلب الحصول على إذن Android 13

عليك أيضًا الإفصاح عن إذن ممارسة، لأنّ كل مسار مرتبط. مع جلسة تمرين (جلسة واحدة = تمرين واحد).

في ما يلي الإذن الذي تحتاج إلى الإفصاح عنه كي تتمكن من كتابة مسارات التمرين الرياضي:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_EXERCISE_ROUTE" />
  <uses-permission
android:name="android.permission.health.WRITE_EXERCISE" />
...
</application>

لقراءة مسارات التمارين الرياضية، عليك طلب الأذونات التالية:

<application>
  <uses-permission
android:name="android.permission.health.READ_EXERCISE_ROUTES" />
  <uses-permission
android:name="android.permission.health.READ_EXERCISE" />
...
</application>

لطلب الأذونات، استخدم PermissionController.createRequestPermissionResultContract() عند عليك أولاً ربط تطبيقك بتطبيق Health Connect. العديد من الأذونات التي قد نريد طلبها:

  • قراءة البيانات الصحية، بما في ذلك بيانات المسار: HealthPermission.getReadPermission(ExerciseSessionRecord::class)
  • كتابة البيانات الصحية، بما في ذلك بيانات المسار: HealthPermission.getWritePermission(ExerciseSessionRecord::class)
  • كتابة بيانات مسار التمرين الرياضي: HealthPermission.PERMISSION_WRITE_EXERCISE_ROUTE

قراءة بيانات المسار وكتابتها

تُدرِج التطبيقات مسارًا من خلال كتابة جلسة تتضمّن مسارًا كحقل.

في حال لم يكن لدى المستخدم أذونات الكتابة ولم يتم ضبط المسار، سيتم لا يتم تحديث التطبيق.

إذا كان تطبيقك لديه إذن تعديل المسار ويحاول تعديل جلسة عن طريق المرور في كائن جلسة بدون مسار، فسيتم حذف المسار الحالي.

عندما يحتاج تطبيقك إلى قراءة بيانات المسار التي يوفّرها تطبيق تابع لجهة خارجية، يطلب من المستخدم السماح بعملية القراءة

طلب مسار من جلسة

إليك طريقة قراءة جلسة في Health Connect وطلب مسار من تلك الجلسة الجلسة:

suspend fun readExerciseSessionAndRoute() {
    val grantedPermissions =
        healthConnectClient.permissionController.getGrantedPermissions()
    if (!grantedPermissions.contains(
          HealthPermission.getReadPermission(ExerciseSessionRecord::class))) {
        // The user doesn't allow the app to read exercise session data.
        return
    }

    val readResponse =
      healthConnectClient.readRecords(
        ReadRecordsRequest(
          ExerciseSessionRecord::class,
          TimeRangeFilter.between(startTime, endTime)
        )
      )
    val exerciseRecord = readResponse.records.first()

    // See https://developer.android.com/training/basics/intents/result#launch
    // for appropriately handling ActivityResultContract.
    val requestExerciseRouteLauncher = fragment.registerForActivityResul
    (ExerciseRouteRequestContract()) { exerciseRoute: ExerciseRoute? ->
            if (exerciseRoute != null) {
                displayExerciseRoute(exerciseRoute)
            } else {
                // Consent was denied
            }
        }

    val exerciseSessionRecord =
      healthConnectClient.readRecord(ExerciseSessionRecord::class, recordId).record

    when (val exerciseRouteResult = exerciseSessionRecord.exerciseRouteResult) {
        is ExerciseRouteResult.Data ->
            displayExerciseRoute(exerciseRouteResult.exerciseRoute)
        is ExerciseRouteResult.ConsentRequired ->
            requestExerciseRouteLauncher.launch(recordId)
        is ExerciseRouteResult.NoData -> Unit // No exercise route to show
        else -> Unit
    }
  }

  fun displayExerciseRoute(route: ExerciseRoute?) {
    val locations = route.route.orEmpty()
    for (location in locations) {
      // Handle location.
    }
  }

كتابة مسار من جلسة

توضح التعليمة البرمجية التالية كيفية تسجيل جلسة تتضمن مسار التمرين:

suspend fun InsertExerciseRoute(healthConnectClient: HealthConnectClient) {
    val grantedPermissions =
        healthConnectClient.permissionController.getGrantedPermissions()
    if (!grantedPermissions.contains(
          getWritePermission(ExerciseSessionRecord::class))) {
        // The user doesn't allow the app to write exercise session data.
        return
    }

    val sessionStartTime = Instant.parse("2023-01-01T10:00:00.00Z")
    val sessionDuration = Duration.ofMinutes(20)

    val exerciseRoute =
      if (getPermissions.contains(PERMISSION_EXERCISE_ROUTE_WRITE) {
        ExerciseRoute(
          listOf(
            ExerciseRoute.Location(
              time = sessionStartTime
              latitude = 6.5483
              longitude = 0.5488
              horizontalAccuracy = Length.meters(2.0)
              verticalAccuracy = Length.meters(2.0),
              altitude = Length.meters(9.0)
            ),
            ExerciseRoute.Location(
              time = sessionStartTime.plus(sessionDuration)
              latitude = 6.4578
              longitude = 0.6577
              horizontalAccuracy = Length.meters(2.0)
              verticalAccuracy = Length.meters(2.0),
              altitude = Length.meters(9.2)
            )
          )
        )
      } else {
        // The user doesn't allow the app to write exercise route data.
        null
      }

    val exerciseSessionRecord =
        ExerciseSessionRecord(
            startTime = /* starting time in milliseconds */,
            startZoneOffset = ZoneOffset.UTC,
            endTime = sessionStartTime.plus(sessionDuration),
            endZoneOffset = ZoneOffset.UTC,
            exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
            title = "Morning Bike Ride",
            exerciseRoute = exerciseRoute
        )

    healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
}