مزامنة البيانات المستمرة

يصف هذا المستند كيفية مزامنة البيانات بين جهاز 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() لإنشاء مادة العرض، كما هو موضّح في النموذج التالي.

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.