يوضّح هذا المستند كيفية مزامنة البيانات بين جهاز Wear OS وأحد الأجهزة الجوّالة.
إرسال البيانات ومزامنتها مباشرةً من الشبكة
أنشئ تطبيقات Wear OS للتواصل مباشرةً مع الشبكة. استخدِم واجهات برمجة التطبيقات نفسها التي تستخدمها لتطوير التطبيقات المتوافقة مع الأجهزة الجوّالة، مع الانتباه إلى بعض اختلافات Wear OS.
مزامنة البيانات باستخدام Wear OS Data Layer API
يعرِض DataClient
واجهة برمجة تطبيقات للمكونات من أجل القراءة أو الكتابة في DataItem
أو
Asset
.
من الممكن ضبط عناصر البيانات ومواد العرض بدون الاتصال بأي أجهزة. تتم مزامنتها عندما تتصل الأجهزة بالشبكة. وهذه البيانات خاصة بتطبيقك ولا يمكن لأحد الوصول إليها إلا من خلال تطبيقك على الأجهزة الأخرى.
تتم مزامنة
DataItem
على جميع الأجهزة في شبكة Wear OS. وتكون هذه الملفات صغيرة الحجم بشكل عام.استخدِم
Asset
لنقل عنصر أكبر، مثل صورة. يتتبّع النظام مواد العرض التي سبق نقلها وينفّذ عملية إزالة تكرار تلقائيًا.
الاستماع إلى الأحداث في الخدمات
وسِّع فئة WearableListenerService
. يدير النظام مراحل تطوير القاعدة WearableListenerService
، ويرتبط بالخدمة عندما يحتاج إلى إرسال عناصر البيانات أو الرسائل، ويفك الارتباط بالخدمة عندما لا يكون هناك حاجة إلى إجراء أي عمل.
الاستماع إلى الأحداث في الأنشطة
نفِّذ واجهة OnDataChangedListener
. استخدِم هذه الواجهة بدلاً من WearableListenerService
عندما تريد الاستماع إلى التغييرات فقط عندما يستخدم
المستخدم تطبيقك بشكل نشط.
نقل البيانات
لإرسال عناصر ثنائية كبيرة عبر بروتوكول النقل عبر البلوتوث، مثل تسجيل صوتي
من جهاز آخر، يمكنك إرفاق
Asset
بعنصر بيانات ثم وضع عنصر البيانات في قاعدة بيانات النسخة المكرّرة.
تعالج مواد العرض تلقائيًا ميزة التخزين المؤقت للبيانات لمنع إعادة الإرسال والحفاظ على معدل نقل البيانات عبر البلوتوث. من الشائع أن يقوم تطبيق متوافق مع الأجهزة الجوّالة بتنزيل صورة وتصغيرها إلى حجم مناسب لعرضها على الجهاز القابل للارتداء وإرسالها إلى تطبيق الجهاز القابل للارتداء كمادة عرض. توضِّح الأمثلة التالية هذا النمط.
ملاحظة: على الرغم من أنّ حجم عناصر البيانات يقتصر نظريًا على 100 كيلوبايت، يمكن استخدام عناصر بيانات أكبر حجمًا عمليًا. بالنسبة إلى عناصر البيانات الأكبر حجمًا، عليك فصل البيانات حسب المسارات الفريدة وتجنُّب استخدام مسار واحد لجميع البيانات. يؤثر نقل مواد العرض الكبيرة في تجربة المستخدم في العديد من الحالات، لذا عليك اختبار تطبيقاتك للمساعدة في ضمان أدائها الجيد عند نقل مواد العرض الكبيرة.
نقل مادة عرض
أنشئ مادة العرض باستخدام إحدى طرق create...()
في فئة
Asset
.
حوِّل صورة نقطية إلى بث بايتات، ثم استخدِم الإجراء
createFromBytes()
لإنشاء مادة العرض، كما هو موضّح في المثال التالي.
private fun createAssetFromBitmap(bitmap: Bitmap): Asset = ByteArrayOutputStream().let { byteStream -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream) Asset.createFromBytes(byteStream.toByteArray()) }
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
:
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)
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
:
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)
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);
استلام مواد العرض
عند إنشاء مادة عرض، قد تحتاج إلى قراءتها واستخراجها على الجانب الآخر من عملية الربط. في ما يلي مثال على كيفية تنفيذ callback لرصد تغيير في مادة العرض واستخراجها:
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 } }
@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.