نقل بيانات Wear OS إلى جهاز جوّال جديد

عند إعداد جهاز Wear OS، يتم ربط جهاز Wear OS بجهاز جوّال محدّد. قد يقرر المستخدم لاحقًا الحصول على جهاز محمول جديد وربط جهاز Wear OS الحالي بهذا الجهاز المحمول الجديد. ويتم تخزين بعض البيانات المرتبطة بجهاز Wear OS على الجهاز الجوّال المتصل حاليًا.

بدءًا من Wear OS 4، عندما يتصل المستخدمون بجهاز جوّال جديد، يمكنهم نقل بيانات Wear OS إلى الجهاز الجوّال الجديد. تتم مزامنة البيانات تلقائيًا عند نقلها.

عندما يطلب المستخدم نقل البيانات، ترسل طبقة البيانات القابلة للارتداء عناصر DataItem المخزَّنة في الأصل على أحد الأجهزة الجوّالة إلى الجهاز الجوّال الآخر. يتيح ذلك تجربة سلسة لمستخدمي تطبيقك.

يوضّح هذا المستند طريقة إعداد تطبيق Wear OS وتطبيقه المتوافق مع الأجهزة الجوّالة لتلبية هذا السيناريو.

الإعداد

تتعامل عملية نقل البيانات مع عناصر DataItem بشكل مختلف حسب التطبيق الذي يملك البيانات:

العناصر التي يملكها تطبيق Wear OS
يتم حفظ هذه العناصر على جهاز Wear OS.
العناصر التي يملكها تطبيق الأجهزة الجوّالة

وتتم أرشفة هذه العناصر على الجهاز القديم. وبعد ذلك، يجمّع النظام البيانات المؤرشفة في عنصر DataItemBuffer ويرسل هذه البيانات إلى التطبيق المتوافق مع الأجهزة الجوّالة المثبّت على الجهاز الجوّال الجديد.

بعد تسليم الأرشيف مباشرةً، تستدعي "طبقة البيانات القابلة للارتداء" أداة استماع onDataChanged()، بالطريقة نفسها التي يتم بها إشعار تطبيقك عندما يكتب الجهاز البيانات التي تعمل بنظام التشغيل Wear OS.

الاحتفاظ بالبيانات المنقولة

إنّ تطبيقك مسؤول عن الحفاظ على العناصر الـ DataItem التي تم نقلها. بعد وقت قصير من تسليم البيانات إلى الجهاز المحمول الجديد، يتم حذف الأرشيف من الجهاز القديم.

تأكّد من صحة كل من الشروط التالية:

  1. ويتم تثبيت تطبيقك على كلا الجهازين الجوّالَين المشاركَين في عملية النقل.
  2. تحتوي تطبيقات الهاتف المحمول، المثبتة على كل جهاز محمول، على توقيعات الحزمة المطابقة.

وبخلاف ذلك، لن يتم تسليم عناصر DataItem المؤرشفة ويتم تجاهلها بدلاً من ذلك.

تلقّي البيانات من الجهاز الجوّال القديم

لتلقّي البيانات على الجهاز الجوّال الجديد الذي تمت أرشفته على الجهاز الجوّال القديم، يجب أن ينفِّذ تطبيقك المتوافق مع الأجهزة الجوّالة ميزة معاودة الاتصال onNodeMigrated() التي تشكّل جزءًا من فئة WearableListenerService. للقيام بذلك، أكمل الخطوات التالية:

  1. في ملف الإصدار الخاص بتطبيق الهاتف المحمول، قم بتضمين الاعتمادية على أحدث إصدار من مكتبة الأجهزة القابلة للارتداء في خدمات Google Play:

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:18.2.0'
    }
    
  2. يمكنك تعريف WearableListenerService وتصديره في ملف بيان تطبيقك:

    <service
    android:name=".MyWearableListenerService"
    android:exported="true">
    <intent-filter>
        ...
        <action android:name="com.google.android.gms.wearable.NODE_MIGRATED" />
        <data android:scheme="wear" />
    </intent-filter>
    </service>
    
  3. إنشاء فئة خدمة تمتد إلى WearableListenerService وتلغي onNodeMigrated()

    Kotlin

    
    class MyWearableListenerService : WearableListenerService() {
        val dataClient: DataClient = Wearable.getDataClient(this)
    
        private fun shouldHandleDataItem(nodeId: String,
                dataItem: DataItem): Boolean {
            // Your logic here
            return dataItem.uri.path?.startsWith("/my_feature_path/") == true
        }
    
        private suspend fun handleDataItem(nodeId: String, dataItem: DataItem) {
            val data = dataItem.data ?: return
            val path = dataItem.uri.path ?: return
            // Your logic here
            if (data.toString().startsWith("Please restore")) {
                dataClient.putDataItem(
                    PutDataRequest.create(path).setData(data))
            }
        }
    
        override fun onNodeMigrated(nodeId: String, archive: DataItemBuffer) {
            val dataItemsToHandle = mutableListOf<DataItem>()
    
            for (dataItem in archive) {
                if (shouldHandleDataItem(nodeId, dataItem)) {
                    dataItemsToHandle.add(dataItem.freeze())
                }
            }
    
            CoroutineScope(Job() + Dispatchers.IO).launch {
                for (dataItem in dataItemsToHandle) {
                    handleDataItem(nodeId, dataItem)
                }
            }
        }
    }
    
    

    Java

    
    public class MyWearableListenerService extends WearableListenerService {
        private final DataClient dataClient = Wearable.getDataClient(this);
    
        private boolean shouldHandleDataItem(String nodeId, DataItem dataItem) {
            // Your logic here
            return Objects.requireNonNull(dataItem.getUri().getPath())
                    .startsWith("/my_feature_path/");
        }
    
        private void handleDataItem(String nodeId, DataItem dataItem) {
            byte[] data = dataItem.getData();
            String path = dataItem.getUri().getPath();
            // Your logic here
            if (data != null && path != null && Arrays.toString(data)
                    .startsWith("Please restore")) {
                assert path != null;
                dataClient.putDataItem(
                        PutDataRequest.create(path).setData(data));
            }
        }
    
        @Override
        public void onNodeMigrated(@NonNull String nodeId, DataItemBuffer archive) {
            List<DataItem> dataItemsToHandle = new ArrayList<>();
    
            for (DataItem dataItem : archive) {
                if (shouldHandleDataItem(nodeId, dataItem)) {
                    dataItemsToHandle.add(dataItem.freeze());
                }
            }
    
            Thread thread = new Thread(() -> {
                for (DataItem dataItem : dataItemsToHandle) {
                    handleDataItem(nodeId, dataItem);
                }
            });
            thread.start();
        }
    }