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

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

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

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

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

الإعداد

تتعامل عملية نقل البيانات مع عناصر DataItem بشكلٍ مختلف، استنادًا إلى التطبيق الذي يملك البيانات:

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

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

بعد تسليم الأرشيف مباشرةً، تستدعي Wearable Data Layer مستمع onNodeMigrated()، تمامًا مثل الطريقة التي يتم بها إرسال إشعار إلى تطبيقك عند كتابة البيانات بواسطة جهاز Wear OS.

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

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

تأكَّد من توفُّر كلّ شرط من الشروط التالية:

  1. تم تثبيت تطبيقك على كلا الجهازَين الجوّالَين المعنيَّين في عملية التحميل/التنزيل.
  2. تتضمّن التطبيقات المتوافقة مع الأجهزة الجوّالة المثبَّتة على كل جهاز جوّال توقيعات حِزم متطابقة.

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

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

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

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

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:19.0.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 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())
                }
            }
    
            // Callback stops automatically after 20 seconds of data processing.
            // If you think you need more time, delegate to a coroutine or thread.
            runBlocking {
                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 Task<DataItem> 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;
                return 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());
                }
            }
    
            for (dataItem in dataItemsToHandle) {
                handleDataItem(nodeId, dataItem);
            }
    
            // Callback stops automatically after 20 seconds of data processing.
            // If you think you need more time, delegate to another thread.
        }
    }