אם אתם רוצים ליצור באפליקציה שלכם חוויה של מעקב אחר השינה, אתם יכולים להשתמש ב-Health Connect כדי לבצע פעולות כמו:
- כתיבת נתוני השינה
- כתיבה של נתוני שלב השינה
- כתיבה של נתוני שינה כמו דופק, רמת החמצן בדם וקצב הנשימה
- קריאת נתוני שינה מאפליקציות אחרות
במדריך הזה מוסבר איך ליצור את תכונות השינה האלה. הוא כולל הסברים על סוגי נתונים, הרשאות, שיטות מומלצות ותהליכי עבודה מומלצים.
סקירה כללית: יצירת כלי מקיף למעקב אחרי השינה
כדי ליצור חוויית מעקב אחר השינה מקיפה באמצעות Health Connect, אפשר לבצע את השלבים העיקריים הבאים:
- הטמעה נכונה של הרשאות על סמך ההרשאות לגישה למידע בריאותי.
- הקלטת סשנים באמצעות
SleepSessionRecord. - כתיבה של סוגי נתונים כמו שלבי שינה, דופק וריווי חמצן באופן עקבי במהלך הסשן.
- ניהול נכון של הרצה ברקע כדי לוודא שמתבצע איסוף רציף של נתונים במהלך הלילה.
- קריאת נתוני סשן לצורך סיכומים וניתוחים אחרי השינה.
תהליך העבודה הזה מאפשר אינטראופרביליות עם אפליקציות אחרות של Health Connect ומאמת את הגישה לנתונים שנשלטת על ידי המשתמש.
לפני שמתחילים
לפני שמטמיעים תכונות שינה:
- משלבים את Health Connect באמצעות התלות המתאימה.
- יוצרים מכונת
HealthConnectClient. - מוודאים שהאפליקציה מטמיעה תהליכי הרשאה בזמן ריצה שמבוססים על Health Permissions.
מושגים מרכזיים
נתוני השינה ב-Health Connect מיוצגים באמצעות כמה רכיבי ליבה. SleepSessionRecord משמש כרשומה מרכזית של נתוני השינה, ומכיל פרטים כמו שעת ההתחלה או הסיום ושלבי השינה. במהלך סשן, יכולים להירשם סוגים שונים של נתונים, כמו HeartRateRecord או OxygenSaturationRecord.
מצב שינה
נתוני השינה מיוצגים על ידי SleepSessionRecord. כל רשומה כוללת:
startTimeendTime-
stages: רשימה שלSleepSessionRecord.Stageכולל שינה עמוקה, שינה קלה, שנת REM ושינה במצב ערות. - מטא-נתונים אופציונליים של הסשן (שם, הערות)
אפליקציות עשויות לכתוב כמה סוגי נתונים שמשויכים לסשן.
סוגי הנתונים
סוגי נתונים נפוצים שנרשמים במהלך רשומת שינה:
-
SleepSessionRecord: מתעד את משך השינה ואת השלבים שלה, כולל שינה עמוקה, שינה קלה, שנת REM וערות. -
HeartRateRecord: תיעוד הדופק במהלך השינה. -
OxygenSaturationRecord: רמת החמצן בדם (סטורציה) שנמדדת במהלך השינה. -
RespiratoryRateRecord: מתעד את קצב הנשימה במהלך השינה.
כל סוג נתונים נשמר כרשומה נפרדת.
שיקולי פיתוח
אפליקציות למעקב אחרי שינה צריכות לפעול לפרקי זמן ארוכים, ולעתים קרובות ברקע כשהמסך כבוי. כשמפתחים תכונות שקשורות לשינה, חשוב לחשוב איך לנהל את הפעילות ברקע ולבקש את ההרשאות הנדרשות לנתוני השינה.
ביצוע ברקע
אפליקציות למעקב אחרי שינה פועלות בדרך כלל בלילה כשהמסך כבוי. במצב הזה, צריך להשתמש ב:
- שירותים שפועלים בחזית לצורך איסוף נתונים
-
WorkManagerלדחיית כתיבה או סנכרון - שיטות לאיגוד נתונים בכמויות גדולות לכתיבה של רשומות רגילות של נתונים פרטניים, כמו קצב הלב
כדי לשמור על רציפות, צריך להקפיד שמזהה הסשן יהיה זהה בכל הפעולות.
הרשאות
האפליקציה צריכה לבקש את ההרשאות הרלוונטיות של Health Connect לפני שהיא קוראת או כותבת נתוני שינה. רשימה מלאה של סוגי הנתונים זמינה במאמר סוגי הנתונים של Health Connect. הרשאות נפוצות לשינה כוללות רשומות שינה ומדדים כמו דופק או רמת החמצן בדם.
הגישה לנתוני השינה מוגנת על ידי ההרשאות הבאות:
android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEP
כדי להוסיף לאפליקציה אפשרות של נתוני שינה, צריך קודם לבקש הרשאות לסוג הנתונים SleepSession.
זו ההרשאה שצריך להצהיר עליה כדי שיהיה אפשר לכתוב נתוני שינה:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
כדי לקרוא את נתוני השינה, צריך לבקש את ההרשאות הבאות:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
בדוגמה הבאה מוצגות בקשות להרשאות עבור רשומת שינה הכוללת נתונים של דופק, רמת החמצן בדם וקצב הנשימה:
אחרי שיוצרים מופע של לקוח, האפליקציה צריכה לבקש הרשאות מהמשתמש. צריך לאפשר למשתמשים להעניק או לדחות הרשאות בכל שלב. כדי לעשות זאת, יוצרים קבוצת הרשאות לסוגי הנתונים הנדרשים. קודם צריך לוודא שההרשאות בקבוצה מוצהרות במניפסט של Android.
val permissions = setOf( HealthPermission.getReadPermission(SleepSessionRecord::class), HealthPermission.getWritePermission(SleepSessionRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class), HealthPermission.getReadPermission(OxygenSaturationRecord::class), HealthPermission.getWritePermission(OxygenSaturationRecord::class), HealthPermission.getReadPermission(RespiratoryRateRecord::class), HealthPermission.getWritePermission(RespiratoryRateRecord::class) )
getGrantedPermissions כדי לבדוק אם האפליקציה כבר קיבלה את ההרשאות הנדרשות. אם לא, משתמשים ב-createRequestPermissionResultContract כדי לבקש את ההרשאות האלה. הפעולה הזו תציג את מסך ההרשאות של Health Connect.
val permissions = setOf( HealthPermission.getReadPermission(StepsRecord::class), HealthPermission.getWritePermission(StepsRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class) ) val requestPermissionsLauncher = rememberLauncherForActivityResult( contract = PermissionController.createRequestPermissionResultContract() ) { grantedPermissions -> if (grantedPermissions.containsAll(permissions)) { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") } } else { coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") } } }
הטמעה של רשומת שינה
בקטע הזה מתואר תהליך העבודה המומלץ לתיעוד נתוני שינה.
כדי להתאים סוגי נתונים כמו HeartRateRecord או OxygenSaturationRecord לרשומת שינה, צריך לתעד אותם עם חותמות זמן שחלות בין startTime לבין endTime של הרשומה. Health Connect לא משתמש במזהה סשן כדי לקשר בין סשנים של שינה לבין נתונים מפורטים. במקום זאת, השיוך הוא מרומז באמצעות חפיפה בין מרווחי זמן. כשקוראים נתוני שינה, אפשר להשתמש בטווח הזמן של סשן כדי לשלוח שאילתה לגבי סוגי נתונים משויכים, כמו שמוסבר במאמר קריאת נתוני שינה.
כתיבת נתוני סשן
אפשר לתעד נתונים מפורטים כמו דופק במהלך סשן שינה, אבל את SleepSessionRecord עצמו צריך לכתוב ב-Health Connect רק אחרי שהסשן מסתיים, למשל כשהמשתמש מתעורר. הרשומה צריכה לכלול את הסשן startTime, endTime ורשימה של אובייקטים SleepSessionRecord.Stage שתועדו במהלך הסשן, כי SleepSessionRecord מחייב ש-endTime יופיע אחרי startTime.
כדי לכתוב רשומת שינה:
- יוצרים מזהה ייחודי של רשומת לקוח.
- כשהמשתמש מתעורר או כשמעקב אחר השינה מופסק, אוספים את כל שלבי השינה ויוצרים
SleepSessionRecord. - מוסיפים את הרשומה באמצעות
insertRecords.
דוגמה:
val clientRecordId = UUID.randomUUID().toString()
val sessionStartTime = LocalDateTime.of(2023, 10, 30, 22, 0).toInstant(ZoneOffset.UTC)
val sessionEndTime = LocalDateTime.of(2023, 10, 31, 7, 0).toInstant(ZoneOffset.UTC)
val stages = mutableListOf<SleepSessionRecord.Stage>()
// Add recorded stages, for example:
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(3600),
endTime = sessionStartTime.plusSeconds(7200),
stage = SleepSessionRecord.STAGE_TYPE_LIGHT)
)
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(7200),
endTime = sessionStartTime.plusSeconds(10800),
stage = SleepSessionRecord.STAGE_TYPE_DEEP)
)
// ... other stages
val session = SleepSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
stages = stages,
metadata = Metadata(clientRecordId = clientRecordId)
)
healthConnectClient.insertRecords(listOf(session))
קריאת נתוני השינה
אפליקציות יכולות לקרוא נתונים של סשנים של שינה ונתונים שקשורים אליהם כדי לסכם את הפעילות, לספק תובנות לגבי הבריאות או לסנכרן נתונים עם שרת חיצוני. לדוגמה, אפשר לקרוא SleepSessionRecord ואז לשלוח שאילתה לגבי HeartRateRecord שהתרחשה באותו מרווח זמן.
סשן קריאה עם נתונים משויכים
אפשר לקרוא סשנים של שינה באמצעות ReadRecordsRequest עם SleepSessionRecord כסוג הרשומה, מסונן לפי טווח זמן. כדי לקרוא נתונים משויכים של סשן נתון, שולחים בקשה שנייה לסוג הנתונים שנבחר, למשל HeartRateRecord – סינון לפי startTime ו-endTime של סשן השינה.
בדוגמה הבאה מוצגות שיטות לקריאת נתוני שינה עם נתוני דופק משויכים לטווח זמן נתון:
suspend fun readSleepSessionsWithAssociatedData(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = SleepSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (sleepRecord in response.records) {
// Process each session
val stages = sleepRecord.stages
val notes = sleepRecord.notes
// To read specific granular data (like heart rate) that occurred during
// this session, use the session's startTime and endTime to filter
// the request for that data type.
val hrResponse = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = HeartRateRecord::class,
timeRangeFilter = TimeRangeFilter.between(
sleepRecord.startTime,
sleepRecord.endTime
)
)
)
for (heartRateRecord in hrResponse.records) {
for (sample in heartRateRecord.samples) {
val bpm = sample.beatsPerMinute
}
}
}
}
שיטות מומלצות
כדי לשפר את מהימנות הנתונים ואת חוויית המשתמש, כדאי לפעול לפי ההנחיות הבאות:
- כתיבה בתדירות גבוהה במהלך מעקב פעיל: כשמפעילים מעקב פעיל, כותבים את הנתונים כשהם זמינים או במרווח זמן מקסימלי של 15 דקות.
- שימוש ב-WorkManager לסנכרון ברקע: שימוש ב-
WorkManagerלכתיבות שנדחות. מומלץ להגדיר מרווח של 15 דקות כדי ליצור איזון בין נתונים בזמן אמת לבין יעילות הסוללה. - בקשות לכתיבת נתונים בקבוצות: אל תכתבו כל אירוע של חיישן בנפרד. כדאי לחלק את הבקשות. Health Connect יכול לטפל בעד 1,000 רשומות לכל בקשת כתיבה.
- שמירה על מזהי סשנים קבועים וייחודיים: צריך להשתמש במזהים עקביים לסשנים. אם עורכים או מעדכנים סשן, שימוש באותו מזהה מונע מהמערכת להתייחס אליו כסשן חדש ונפרד.
- שימוש באצווה לסוגי נתונים: כדי לצמצם את התקורה של קלט/פלט ולשמור על חיי הסוללה, כדאי לקבץ את נקודות הנתונים לקריאה יחידה של
insertRecordsבמקום לכתוב כל נקודה בנפרד. - כדי למנוע כתיבה של נתונים כפולים: משתמשים במזהי לקוח: כשיוצרים רשומות, מגדירים
metadata.clientRecordId. מערכת Health Connect משתמשת במזהה הזה כדי לזהות רשומות ייחודיות. אם מנסים לכתוב רשומה עםclientRecordIdשכבר קיים, מערכת Health Connect מתעלמת מהכפילות או מעדכנת את הרשומה הקיימת במקום ליצור רשומה חדשה. הגדרתmetadata.clientRecordIdהיא הדרך היעילה ביותר למנוע כפילויות במהלך ניסיונות חוזרים לסנכרון או התקנה מחדש של אפליקציה.val record = StepsRecord( count = 100, startTime = startTime, endTime = endTime, startZoneOffset = ZoneOffset.UTC, endZoneOffset = ZoneOffset.UTC, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "daily_steps_2023_10_27_user_123" ) )
- בדיקת נתונים קיימים: לפני שמסנכרנים, שולחים שאילתה לטווח הזמן כדי לראות אם רשומות מהאפליקציה כבר קיימות.
- מוודאים שחותמות הזמן לא חופפות: חשוב לוודא שסשן חדש לא מתחיל לפני שהסשן הקודם מסתיים. חפיפה בין סשנים עלולה לגרום לקונפליקטים בלוחות הבקרה של הכושר ובחישובים של הסיכומים.
- לספק נימוקים ברורים להרשאה: צריך להשתמש בתהליך
Permission.createIntentכדי להסביר למה האפליקציה צריכה גישה לנתונים בתחום הבריאות. לדוגמה: 'כדי לעקוב אחרי המגמות של לחץ הדם ולספק תובנות'. - בדיקת סשנים ארוכים: מעקב אחרי צריכת הסוללה במהלך סשנים שנמשכים כמה שעות כדי לוודא שמרווח האצווה ושימוש בחיישן לא מרוקנים את הסוללה של המכשיר.
- התאמת חותמות הזמן לקצב החיישנים: כדי לשמור על רמת מהימנות גבוהה של הנתונים, צריך להתאים את חותמות הזמן של הרשומה לתדירות בפועל של החיישנים.
בדיקה
כדי לוודא שהנתונים נכונים ושהמשתמשים נהנים מחוויה איכותית, כדאי לפעול לפי אסטרטגיות הבדיקה האלה ולעיין במסמכי התיעוד הרשמיים בנושא בדיקת תרחישי שימוש נפוצים.
כלי אימות
- ארגז הכלים של Health Connect: אפשר להשתמש באפליקציה הנלווית הזו כדי לבדוק רשומות באופן ידני, למחוק נתוני בדיקה ולבצע סימולציה של שינויים במסד הנתונים. זו הדרך הכי טובה לוודא שהרשומות שלכם מאוחסנות בצורה נכונה.
- בדיקות יחידה באמצעות
FakeHealthConnectClient: אפשר להשתמש בספריית הבדיקות כדי לוודא איך האפליקציה מטפלת במקרים קיצוניים, כמו ביטול הרשאה או חריגות ב-API, בלי צורך במכשיר פיזי.
רשימת משימות לבדיקת איכות
ארכיטקטורה אופיינית
הטמעה של מעקב אחר השינה כוללת בדרך כלל:
| רכיב | מנהל |
|---|---|
| בקר סשנים | מצב הסשן טיימר לוגיקה של עיבוד באצווה בקרים של סוגי נתונים איסוף נתונים |
| שכבת מאגר (עוטפת פעולות של Health Connect): | הוספת סשן הוספת סוגי נתונים הוספת שלבי שינה קריאת סיכומי סשנים |
| שכבת ממשק המשתמש (מסכים): | משך זמן סוגי נתונים בזמן אמת תרשים להמחשת שלב השינה |
פתרון בעיות
| תיאור הבעיה | גורם אפשרי | רזולוציה |
|---|---|---|
| סוגי נתונים חסרים (לדוגמה, דופק) | הרשאות הכתיבה חסרות או שהמסננים של הזמן שגויים. | בודקים שביקשתם מהמשתמש הרשאה לסוג הנתונים הספציפי והמשתמש העניק לכם אותה. צריך לוודא שמשתמשים ב-ReadRecordsRequest בTimeRangeFilter שתואם לסשן. מידע נוסף על הרשאות |
| הכתיבה של הסשן נכשלת | חותמות זמן חופפות. | יכול להיות שאפליקציית Health Connect תדחה רשומות שחופפות לנתונים קיימים מאותה אפליקציה. צריך לוודא שערך startTime של סשן חדש מופיע אחרי ערך endTime של הסשן הקודם. |
| לא מתועדים נתוני חיישנים במהלך השינה | השירות שפועל בחזית הופסק או שהוא לא פעיל. | כדי לאסוף נתוני חיישנים במהלך הלילה כשהמסך כבוי, אפשר להשתמש בשירות חזיתי עם foregroundServiceType="health". |
| מופיעות רשומות כפולות | חסר: clientRecordId |
צריך להקצות clientRecordId ייחודי ב-Metadata של כל רשומה. כך, אם אותם נתונים נכתבים פעמיים במהלך ניסיון חוזר לסנכרון, Health Connect יכול לבצע ביטול כפילויות. אפשר לעיין בשיטות מומלצות. |
שלבים נפוצים לניפוי באגים
| בודקים את מצב ההרשאה. | תמיד צריך להתקשר אל getPermissionStatus() לפני שמנסים לבצע פעולת קריאה או כתיבה. המשתמשים יכולים לבטל את ההרשאות בהגדרות המערכת בכל שלב. |
| בודקים את מצב ההפעלה. | אם האפליקציה לא אוספת נתונים ברקע, צריך לוודא שהצהרתם על ההרשאות הנכונות בקובץ AndroidManifest.xml ושהמשתמש לא העביר את האפליקציה למצב 'הגבלת השימוש בסוללה'. |