המדריך הזה תואם לגרסה 1.1.0-alpha12 של Health Connect.
לרוב האפליקציות שמשולבות עם Health Connect יש מאגר נתונים משלהן שמשמש כמקור האמת. אפליקציית Health Connect מספקת דרכים לשמור על סנכרון האפליקציה.
בהתאם לארכיטקטורה של האפליקציה, תהליך הסנכרון עשוי לכלול חלק מהפעולות הבאות או את כולן:
- העברת נתונים חדשים או מעודכנים ממאגר הנתונים של האפליקציה אל Health Connect.
- שליפת שינויים בנתונים מ-Health Connect למאגר הנתונים של האפליקציה.
- למחוק נתונים מ-Health Connect כשהם נמחקים במאגר הנתונים של האפליקציה.
בכל מקרה, חשוב לוודא שתהליך הסנכרון שומר על התאמה בין Health Connect לבין מאגר הנתונים של האפליקציה.
העברת נתונים ל-Health Connect
החלק הראשון בתהליך הסנכרון הוא הזנת נתונים ממאגר הנתונים של האפליקציה למאגר הנתונים של Health Connect.
הכנת הנתונים
בדרך כלל, הרשומות במאגר הנתונים של האפליקציה כוללות את הפרטים הבאים:
- מפתח ייחודי, כמו
UUID. - גרסה או חותמת זמן.
כשמסנכרנים נתונים עם Health Connect, צריך לזהות ולהעביר רק את הנתונים שנוספו, עודכנו או נמחקו מאז הסנכרון האחרון.
כתיבת נתונים ב-Health Connect
כדי להזין נתונים ל-Health Connect, מבצעים את השלבים הבאים:
- מקבלים רשימה של רשומות חדשות, מעודכנות או שנמחקו ממאגר הנתונים של האפליקציה.
- לכל רשומה, יוצרים אובייקט
Recordשמתאים לסוג הנתונים. לדוגמה, אפשר ליצור אובייקטWeightRecordלנתונים שקשורים למשקל. מציינים אובייקט
Metadataעם כלRecord. השאלה מתייחסת גם ל-clientRecordId, שהוא מזהה ממאגר הנתונים של האפליקציה שבו אפשר להשתמש כדי לזהות באופן ייחודי את הרשומה. אפשר להשתמש במפתח הייחודי הקיים. אם הנתונים שלכם הם בפורמט של גרסאות, צריך לספק גםclientRecordVersionשתואם לפורמט הגרסאות שבו הנתונים שלכם משתמשים. אם אין גרסה, אפשר להשתמש בערךLongשל חותמת הזמן הנוכחית כחלופה.val recordVersion = 0L // Specify as needed // The clientRecordId is an ID that you choose for your record. This // is often the same ID you use in your app's datastore. val clientRecordId = "<your-record-id>" val record = WeightRecord( metadata = Metadata( clientRecordId = clientRecordId, clientRecordVersion = recordVersion, device = Device(type = Device.TYPE_SCALE) ), weight = Mass.kilograms(62.0), time = Instant.now(), zoneOffset = ZoneOffset.UTC, ) healthConnectClient.insertRecords(listOf(record))
Upsert נתונים ל-Health Connect באמצעות
insertRecords. כשמבצעים פעולת Upsert על נתונים, כל הנתונים הקיימים ב-Health Connect נמחקים ומוחלפים בנתונים חדשים, כל עוד הערכים שלclientRecordIdקיימים במאגר הנתונים של Health Connect והערך שלclientRecordVersionגבוה מהערך הקיים. אחרת, הנתונים שנוספו או עודכנו ייכתבו כנתונים חדשים.healthConnectClient.insertRecords(arrayListOf(record))
כדי לקבל מידע על שיקולים מעשיים לגבי הזנת נתונים, אפשר לעיין בשיטות המומלצות בנושא כתיבת נתונים.
שמירת מזהים של Health Connect
אם האפליקציה שלכם קוראת גם נתונים מ-Health Connect, צריך לאחסן את id
של הרשומות ב-Health Connect אחרי שמבצעים פעולת upsert. אתם צריכים את id כדי לעבד מחיקות כשאתם שולפים שינויים בנתונים מ-Health Connect.
הפונקציה insertRecords מחזירה InsertRecordsResponse שמכיל את רשימת הערכים id.
משתמשים בתשובה כדי לקבל את מזהי הרשומות ומאחסנים אותם.
val response = healthConnectClient.insertRecords(listOf(record)) for (recordId in response.recordIdsList) { // Store recordId to your app's datastore }
שליפת נתונים מ-Health Connect
החלק השני בתהליך הסנכרון הוא שליפת שינויים בנתונים מ-Health Connect למאגר הנתונים של האפליקציה. השינויים בנתונים יכולים לכלול עדכונים ומחיקות.
קבלת טוקן שינויים
כדי לקבל רשימה של שינויים לשליפה מ-Health Connect, האפליקציה צריכה לעקוב אחרי טוקנים של שינויים. אתם יכולים להשתמש בהם כשאתם מבקשים שינויים כדי לקבל גם רשימה של שינויים בנתונים וגם טוקן שינויים חדש לשימוש בפעם הבאה.
כדי לקבל אסימון Changes, קוראים ל-getChangesToken ומספקים את סוגי הנתונים הנדרשים.
val changesToken = healthConnectClient.getChangesToken( ChangesTokenRequest(recordTypes = setOf(WeightRecord::class)) )
בדיקה אם יש שינויים בנתונים
אחרי שמקבלים את אסימון השינויים, משתמשים בו כדי לקבל את כל השינויים. מומלץ ליצור לולאה כדי לעבור על כל השינויים ולבדוק אם יש שינויים זמינים בנתונים. אלה השלבים:
- מתקשרים אל
getChangesבאמצעות הטוקן כדי לקבל רשימה של שינויים. - בודקים כל שינוי כדי לראות אם הוא מסוג
UpsertionChangeאוDeletionChange, ומבצעים את הפעולות הנדרשות.- במקרה של
UpsertionChange, צריך לקחת בחשבון רק שינויים שלא בוצעו באפליקציה שקוראת ל-API, כדי לוודא שלא מתבצע ייבוא חוזר של נתונים.
- במקרה של
- מקצים את אסימון השינויים הבא כאסימון החדש.
- חוזרים על שלבים 1 עד 3 עד שלא נשארים שינויים.
- לאחסן את האסימון הבא ולשמור אותו לייבוא עתידי.
suspend fun processChanges(context: Context, token: String): String { var nextChangesToken = token do { val response = healthConnectClient.getChanges(nextChangesToken) response.changes.forEach { change -> when (change) { is UpsertionChange -> if (change.record.metadata.dataOrigin.packageName != context.packageName) { processUpsertionChange(change) } is DeletionChange -> processDeletionChange(change) } } nextChangesToken = response.nextChangesToken } while (response.hasMore) // Return and store the changes token for use next time. return nextChangesToken }
כדי לקבל מידע על שיקולים מעשיים לגבי שליפת נתונים, אפשר לעיין בשיטות המומלצות בנושא סנכרון נתונים.
עיבוד שינויים בנתונים
לשקף את השינויים במאגר הנתונים של האפליקציה. ב-UpsertionChange, משתמשים ב-id וב-lastModifiedTime מ-metadata כדי לעדכן או להוסיף את הרשומה.
במקרה של DeletionChange, משתמשים בid שמופיע כדי למחוק את הרשומה.
לשם כך, צריך לאחסן את הרשומה id כמו שמתואר במאמר אחסון מזהים של Health Connect.
מחיקת נתונים מ-Health Connect
כשמשתמש מוחק את הנתונים שלו מהאפליקציה שלכם, חשוב לוודא שהנתונים מוסרים גם מ-Health Connect. כדי לעשות את זה, משתמשים ב-deleteRecords. הפונקציה מקבלת סוג רשומה ורשימה של ערכי id ו-clientRecordId
ומאפשרת למחוק כמה נתונים בבת אחת. אפשר גם להשתמש בחלופה deleteRecords שמקבלת timeRangeFilter.
סנכרון עם זמן אחזור נמוך ממכשירים לבישים
כדי לסנכרן נתונים ממכשיר כושר לביש אל Health Connect עם זמן אחזור נמוך,
משתמשים ב-CompanionDeviceService. הגישה הזו מתאימה למכשירים שתומכים בהתראות או באינדיקציות של BLE GATT ולמכשירים עם Android מגרסה 8.0 (רמת API 26) ואילך. CompanionDeviceService מאפשר לאפליקציה לקבל נתונים ממכשירים לבישים ולכתוב אותם ב-Health Connect, גם כשהאפליקציה לא פועלת. מידע נוסף על שיטות מומלצות ל-BLE זמין במאמר בנושא סקירה כללית של Bluetooth Low Energy.
שיוך המכשיר
קודם כל, האפליקציה צריכה להנחות את המשתמש בתהליך חד-פעמי לשיוך המכשיר הלביש לאפליקציה באמצעות CompanionDeviceManager. הפעולה הזו מעניקה לאפליקציה את ההרשאות הנדרשות כדי לבצע פעולות במכשיר. מידע נוסף זמין במאמר בנושא התאמת מכשירים נלווים.
הצהרה על השירות בקובץ המניפסט
לאחר מכן, צריך להצהיר על CompanionDeviceService בקובץ המניפסט של האפליקציה. מוסיפים את הטקסט הבא לAndroidManifest.xml:
<manifest ...>
<application ...>
<service
android:name=".MyWearableService"
android:exported="true"
android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE">
<intent-filter>
<action android:name="android.companion.CompanionDeviceService" />
</intent-filter>
</service>
</application>
</manifest>
יצירת CompanionDeviceService
לבסוף, יוצרים כיתה שמרחיבה את CompanionDeviceService. השירות הזה מטפל בחיבור למכשיר הלביש ומקבל נתונים באמצעות קריאות חוזרות (callbacks) של BLE GATT. כשמתקבלים נתונים חדשים, הם נכתבים מיד ב-Health Connect.
private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private var healthConnectClient: HealthConnectClient? = null private var bluetoothGatt: BluetoothGatt? = null override fun onDeviceAppeared(address: String) { super.onDeviceAppeared(address) healthConnectClient = HealthConnectClient.getOrCreate(this) serviceScope.launch { val granted = healthConnectClient?.permissionController?.getGrantedPermissions() // 1. Check permissions ONCE when the device connects if (granted?.contains(HealthPermission.getWritePermission(HeartRateRecord::class)) ?: false) { // This is where you'd actually start the Bluetooth connection // bluetoothGatt = gattCallback.connect(...) } // 2. Do your initial database read readExerciseSessionAndRoute() } } private val gattCallback = object : BluetoothGattCallback() { override fun onCharacteristicChanged( gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray ) { super.onCharacteristicChanged(gatt, characteristic, value) // 3. ONLY process the incoming data here val rawData = value serviceScope.launch { // parseWearableData(rawData) // insertExerciseRoute() or writeToHealthConnect() } } }
שיטות מומלצות לסינכרון נתונים
הגורמים הבאים משפיעים על תהליך הסנכרון.
תוקף הטוקן
אסימון Changes שלא נעשה בו שימוש יפוג תוך 30 יום, ולכן צריך להשתמש באסטרטגיית סנכרון שתמנע אובדן מידע במקרה כזה. האסטרטגיה יכולה לכלול את הגישות הבאות:
- מחפשים במאגר הנתונים של האפליקציה את הרשומה האחרונה שהייתה בשימוש, שכוללת גם
idמ-Health Connect. - שליחת בקשה לרישומים מ-Health Connect שמתחילים בחותמת זמן ספציפית, ואז הוספה או עדכון שלהם במאגר הנתונים של האפליקציה.
- שליחת בקשה לקבלת אסימון שינויים כדי לשריין אותו לפעם הבאה שיהיה צורך בו.
שיטות מומלצות לניהול שינויים
אם האפליקציה מקבלת טוקנים של שינויים שהם פסולים או שתוקפם פג, מומלץ להשתמש באסטרטגיות הניהול הבאות בהתאם ליישום שלהן בלוגיקה שלכם:
- קריאה וביטול כפילויות של כל הנתונים. זו השיטה הכי מומלצת.
- שומרים את חותמת הזמן של הפעם האחרונה שבה האפליקציה קראה נתונים מ-Health Connect.
- כשפג תוקף הטוקן, צריך לקרוא מחדש את כל הנתונים מהחותמת האחרונה או מ-30 הימים האחרונים. לאחר מכן, מסירים את הכפילויות מהנתונים שנקראו קודם באמצעות מזהים.
- מומלץ להטמיע Client-ID, כי הוא נדרש לעדכוני נתונים.
- קריאת נתונים רק מאז חותמת הזמן האחרונה של הקריאה. כתוצאה מכך, יכול להיות שיהיו אי-התאמות מסוימות בנתונים בסביבות הזמן של תפוגת אסימון השינויים, אבל תקופת הזמן קצרה יותר ויכולה להימשך כמה שעות עד כמה ימים.
- שומרים את חותמת הזמן של הפעם האחרונה שבה האפליקציה קראה נתונים מ-Health Connect.
- כשפג תוקף האסימון, כל הנתונים נקראים מהחותמת הזו ואילך.
- מחיקה ואז קריאת נתונים מ-30 הימים האחרונים. ההתנהגות הזו דומה יותר למה שקורה בשילוב הראשון.
- מחיקת כל הנתונים שהאפליקציה קראה מ-Health Connect ב-30 הימים האחרונים.
- אחרי המחיקה, קוראים שוב את כל הנתונים האלה.
- קריאת נתונים מ-30 הימים האחרונים ללא ביטול כפילויות. זוהי האסטרטגיה הכי פחות מומלצת, והיא גורמת לכך שיוצגו למשתמשים נתונים כפולים.
- מחיקת כל הנתונים שהאפליקציה קראה מ-Health Connect ב-30 הימים האחרונים.
- אפשר להזין ערכים כפולים.
אסימונים של שינויים בסוג הנתונים
אם האפליקציה צורכת יותר מסוג נתונים אחד באופן עצמאי, צריך להשתמש ב-Changes Tokens נפרדים לכל סוג נתונים. אפשר להשתמש ברשימה של כמה סוגי נתונים עם Changes Sync API רק אם סוגי הנתונים האלה נצרכים ביחד או לא נצרכים בכלל.
קריאות בחזית
אפליקציות יכולות לקרוא נתונים מ-Health Connect רק כשהן פועלות בחזית. במהלך סנכרון הנתונים מ-Health Connect, יכול להיות שהגישה ל-Health Connect תיקטע בכל שלב. לדוגמה, האפליקציה צריכה לטפל בהפרעות באמצע הסנכרון כשקוראים כמות גדולה של נתונים מ-Health Connect, ולהמשיך בפעם הבאה שהאפליקציה נפתחת.
קריאה ברקע
אתם יכולים לבקש שהאפליקציה שלכם תפעל ברקע ותקרא נתונים מ-Health Connect. אם תבקשו את ההרשאה Background Read, המשתמש יוכל להעניק לאפליקציה שלכם גישה לקריאת נתונים ברקע.
ייבוא תזמונים
מכיוון שלא ניתן לשלוח לאפליקציה שלך התראות על נתונים חדשים, צריך לבדוק אם יש נתונים חדשים בשני מקומות:
- בכל פעם שהאפליקציה פעילה בחזית. במקרה הזה, כדאי להשתמש באירועים במחזור החיים.
- מדי פעם, כשהאפליקציה בחזית. התראה למשתמשים כשיש נתונים חדשים, כדי שיוכלו לעדכן את המסך ולראות את השינויים.