במאמר הזה מוסבר איך לסנכרן נתונים בין מכשיר Wear OS לבין מכשיר נייד.
שליחה וסנכרון של נתונים ישירות מהרשת
פיתוח אפליקציות ל-Wear OS שמתקשרות ישירות עם הרשת. משתמשים באותם ממשקי API שבהם משתמשים לפיתוח לאפליקציות לנייד, אבל צריך לזכור שיש כמה הבדלים ספציפיים ל-WearOS.
סנכרון נתונים באמצעות Wear OS Data Layer API
DataClient
חושף API לרכיבים כדי לקרוא או לכתוב ל-DataItem
או ל-Asset
.
אפשר להגדיר פריטי נתונים ונכסים גם כשלא מחוברים למכשירים. הם מסונכרנים כשהמכשירים מתחברים לרשת. הנתונים האלה פרטיים לאפליקציה שלכם, ורק האפליקציה שלכם יכולה לגשת אליהם במכשירים אחרים.
DataItem
מסונכרן בין כל המכשירים ברשת Wear OS. הם בדרך כלל קטנים.אפשר להשתמש ב-
Asset
כדי להעביר אובייקט גדול יותר, כמו תמונה. המערכת עוקבת אחרי הנכסים שכבר הועברו ומבצעת הסרת כפילויות באופן אוטומטי.
האזנה לאירועים בשירותים
הארכת השיעור WearableListenerService
. המערכת מנהלת את מחזור החיים של WearableListenerService
הבסיסי, ומקשרת לשירות כשהיא צריכה לשלוח פריטי נתונים או הודעות, ומבטלת את הקישור לשירות כשאין צורך בפעולה.
האזנה לאירועים בפעילויות
מטמיעים את הממשק OnDataChangedListener
. אפשר להשתמש בממשק הזה במקום ב-WearableListenerService
כשרוצים להאזין לשינויים רק כשהמשתמש משתמש באפליקציה באופן פעיל.
העברת נתונים
כדי לשלוח אובייקטים בינאריים גדולים (BLOB) דרך פרוטוקול Bluetooth, כמו הקלטת קול ממכשיר אחר, אפשר לצרף
Asset
לפריט נתונים ואז להכניס את פריט הנתונים למאגר הנתונים המשוכפל.
הנכסים מטפלים אוטומטית בשמירת נתונים במטמון כדי למנוע שידור חוזר ולחסוך ברוחב הפס של Bluetooth. דפוס נפוץ הוא שאפליקציה לנייד מורידה תמונה, מצמצמת אותה לגודל מתאים לתצוגה במכשיר הלביש, ומעבירה אותה לאפליקציה למכשיר הלביש כנכס. הדוגמאות הבאות ממחישות את התבנית הזו.
הערה: למרות שהגודל של פריטי נתונים מוגבל באופן תיאורטי ל-100KB, בפועל אפשר להשתמש בפריטי נתונים גדולים יותר. בפריטי נתונים גדולים יותר, צריך להפריד את הנתונים לפי נתיבים ייחודיים ולא להשתמש בנתיב יחיד לכל הנתונים. העברה של נכסים גדולים משפיעה על חוויית המשתמש במקרים רבים, ולכן מומלץ לבדוק את האפליקציות כדי לוודא שהן פועלות בצורה טובה כשמעבירים נכסים גדולים.
העברת נכס
יוצרים את הנכס באמצעות אחת משיטות create...()
במחלקה
Asset
.
ממירים מפת סיביות לזרם בייטים ואז קוראים ל-
createFromBytes()
כדי ליצור את הנכס, כמו בדוגמה הבאה.
Kotlin
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
Java
private static Asset createAssetFromBitmap(Bitmap bitmap) { final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); return Asset.createFromBytes(byteStream.toByteArray()); }
לאחר מכן, מצרפים את הנכס לפריט נתונים באמצעות השיטה putAsset()
ב-
DataMap
או ב-
PutDataRequest
. לאחר מכן מכניסים את פריט הנתונים למאגר הנתונים באמצעות השיטה
putDataItem()
, כמו בדוגמאות הבאות.
בדוגמה הבאה נעשה שימוש ב-PutDataRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataRequest.create("/image").apply { putAsset("profileImage", asset) } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataRequest request = PutDataRequest.create("/image"); request.putAsset("profileImage", asset); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
בדוגמה הבאה נעשה שימוש ב-PutDataMapRequest
:
Kotlin
val asset: Asset = BitmapFactory.decodeResource(resources, R.drawable.image).let { bitmap -> createAssetFromBitmap(bitmap) } val request: PutDataRequest = PutDataMapRequest.create("/image").run { dataMap.putAsset("profileImage", asset) asPutDataRequest() } val putTask: Task<DataItem> = Wearable.getDataClient(context).putDataItem(request)
Java
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); Asset asset = createAssetFromBitmap(bitmap); PutDataMapRequest dataMap = PutDataMapRequest.create("/image"); dataMap.getDataMap().putAsset("profileImage", asset); PutDataRequest request = dataMap.asPutDataRequest(); Task<DataItem> putTask = Wearable.getDataClient(context).putDataItem(request);
קבלת נכסים
כשיוצרים נכס, סביר להניח שתרצו לקרוא אותו ולחלץ אותו בצד השני של החיבור. דוגמה להטמעה של פונקציית הקריאה החוזרת כדי לזהות שינוי בנכס ולחלץ את הנכס:
Kotlin
override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents .filter { it.type == DataEvent.TYPE_CHANGED && it.dataItem.uri.path == "/image" } .forEach { event -> val bitmap: Bitmap? = DataMapItem.fromDataItem(event.dataItem) .dataMap.getAsset("profileImage") .let { asset -> loadBitmapFromAsset(asset) } // Do something with the bitmap } } fun loadBitmapFromAsset(asset: Asset): Bitmap? { // Convert asset into a file descriptor and block until it's ready val assetInputStream: InputStream? = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) ?.inputStream return assetInputStream?.let { inputStream -> // Decode the stream into a bitmap BitmapFactory.decodeStream(inputStream) } ?: run { Log.w(TAG, "Requested an unknown Asset.") null } }
Java
@Override public void onDataChanged(DataEventBuffer dataEvents) { for (DataEvent event : dataEvents) { if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/image")) { DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); Asset profileAsset = dataMapItem.getDataMap().getAsset("profileImage"); Bitmap bitmap = loadBitmapFromAsset(profileAsset); // Do something with the bitmap } } } public Bitmap loadBitmapFromAsset(Asset asset) { if (asset == null) { throw new IllegalArgumentException("Asset must be non-null"); } // Convert asset into a file descriptor and block until it's ready InputStream assetInputStream = Tasks.await(Wearable.getDataClient(context).getFdForAsset(asset)) .getInputStream(); if (assetInputStream == null) { Log.w(TAG, "Requested an unknown Asset."); return null; } // Decode the stream into a bitmap return BitmapFactory.decodeStream(assetInputStream); }
מידע נוסף זמין בפרויקט לדוגמה של DataLayer ב-GitHub.