במאמר הזה מוסבר איך לסנכרן נתונים בין מכשיר Wear OS לבין טלפון. בהנחיות הכלליות מוסבר מתי כדאי להשתמש ב-Data Layer API ומתי כדאי להשתמש בתשתית שלכם.
שליחה וסנכרון של נתונים ישירות מהרשת
פיתוח אפליקציות ל-Wear OS שמתקשרות ישירות עם הרשת. משתמשים באותם ממשקי API שבהם משתמשים לפיתוח לאפליקציות לנייד, אבל צריך לזכור שיש כמה הבדלים ספציפיים ל-WearOS.
סנכרון נתונים באמצעות Wear OS Data Layer API
DataClient חושף API לרכיבים כדי לקרוא או לכתוב ל-DataItem או ל-Asset.
אפשר להגדיר פריטי נתונים ונכסים גם כשלא מחוברים למכשירים. הם מסונכרנים כשהמכשירים מתחברים לרשת. הנתונים האלה פרטיים לאפליקציה שלכם, ורק האפליקציה שלכם יכולה לגשת אליהם במכשירים אחרים.
DataItemמסונכרן בין כל המכשירים ברשת Wear OS. הם בדרך כלל קטנים.משתמשים ב-
Assetכדי להעביר אובייקט גדול יותר, כמו תמונה. המערכת עוקבת אחרי הנכסים שכבר הועברו ומבצעת הסרת כפילויות באופן אוטומטי.
האזנה לאירועים בשירותים
מאריכים את השיעור WearableListenerService. המערכת מנהלת את מחזור החיים של WearableListenerService הבסיסי, ומקשרת לשירות כשהיא צריכה לשלוח פריטי נתונים או הודעות, ומבטלת את הקישור לשירות כשאין צורך בפעולה.
האזנה לאירועים בפעילויות
הטמעה של הממשק OnDataChangedListener. אפשר להשתמש בממשק הזה במקום ב-WearableListenerService כשרוצים להאזין לשינויים רק כשהמשתמש משתמש באפליקציה באופן פעיל.
description: Transfer large binary objects, such as images, between Android phones and Wear OS watches using Assets in the Data Layer API. keywords_public: Wear OS, Data Layer API, Assets, Bluetooth data transfer, data synchronization, DataMap, PutDataRequest
סנכרון נתונים
כדי לשתף אובייקטים בינאריים גדולים דרך פרוטוקול Bluetooth, כמו הקלטה קולית ממכשיר אחר, אפשר לצרף Asset לפריט נתונים ואז להכניס את פריט הנתונים למאגר הנתונים המשוכפל. עם זאת, אם מדובר באוסף נתונים לשיתוף חד-פעמי בין שני מכשירים מחוברים, כדאי לשקול אם העברה ישירה פשוטה יותר תתאים יותר.
הערה: Data Layer API יכול לשלוח הודעות ולסנכרן נתונים רק עם טלפונים שמריצים Android או עם שעוני Wear OS. אם מכשיר Wear OS משויך למכשיר iOS, Data Layer API לא יפעל.
לכן, לא מומלץ להשתמש ב-Data Layer API כדרך העיקרית לתקשר עם רשת. במקום זאת, צריך לפעול לפי אותו דפוס באפליקציה ל-Wear OS כמו באפליקציה לטלפון – עם כמה הבדלים קלים, כפי שמתואר במאמר גישה לרשת וסנכרון ב-Wear OS.
הנכסים מטפלים אוטומטית בשמירת נתונים במטמון כדי למנוע שידור חוזר ולחסוך ברוחב הפס של Bluetooth. דפוס נפוץ הוא שאפליקציה לטלפון מורידה תמונה, מצמצמת אותה לגודל מתאים לתצוגה בשעון ומשתפת אותה עם אפליקציית שעון חכם כנכס. בדוגמאות הבאות אפשר לראות את התבנית הזו.
העברת נכס
יוצרים את הנכס באמצעות אחת מהשיטות של create...() במחלקה Asset. ממירים מפת סיביות למערך בייטים ואז קוראים ל-createFromBytes() כדי ליצור את הנכס, כמו בדוגמה הבאה.
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
לאחר מכן, מצרפים את הנכס לפריט נתונים באמצעות השיטה putAsset() ב-DataMap או ב-PutDataRequest. לאחר מכן, מכניסים את פריט הנתונים למאגר הנתונים באמצעות השיטה putDataItem(), כמו בדוגמאות הבאות.
בדוגמה הבאה נעשה שימוש ב-PutDataRequest:
private fun Context.sendImagePutDataRequest(): Task<DataItem> { val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk)) val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request) return putTask }
בדוגמה הבאה נעשה שימוש ב-PutDataMapRequest:
private fun Context.sendImagePutDataMapRequest(): Task<DataItem> { val asset: Asset = createAssetFromBitmap(BitmapFactory.decodeResource(resources, R.drawable.ic_walk)) val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(this).putDataItem(request) return putTask }
קבלת נכסים
אחרי שיוצרים נכס, בדרך כלל קוראים אותו ומחלצים אותו בצד השני של החיבור. בדוגמה הבאה אפשר לראות איך מטמיעים את פונקציית הקריאה החוזרת כדי לזהות שינוי בנכס ולחלץ את הנכס:
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val asset = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") asset?.let { safeAsset -> lifecycleScope.launch { val bitmap = loadBitmapFromAsset(safeAsset) // Do something with the bitmap } } } } private suspend fun loadBitmapFromAsset(asset: Asset): Bitmap? = withContext(Dispatchers.IO) { try { val assetResult = Wearable.getDataClient(this@DataLayerActivity2) .getFdForAsset(asset) .await() assetResult?.inputStream?.use { inputStream -> BitmapFactory.decodeStream(inputStream) } } catch (e: Exception) { e.printStackTrace() null } }
מידע נוסף זמין בפרויקט לדוגמה של DataLayer ב-GitHub.