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

يوضّح هذا المستند كيفية مزامنة البيانات بين جهاز 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.