โอนข้อมูล Wear OS ไปยังอุปกรณ์เคลื่อนที่เครื่องใหม่

เมื่อผู้ใช้ตั้งค่าอุปกรณ์ Wear OS จะเป็นการเชื่อมต่ออุปกรณ์ Wear OS กับอุปกรณ์เคลื่อนที่เครื่องหนึ่งๆ ผู้ใช้อาจตัดสินใจซื้ออุปกรณ์เคลื่อนที่เครื่องใหม่ในภายหลัง และเชื่อมต่ออุปกรณ์ Wear OS เครื่องที่มีอยู่กับอุปกรณ์เคลื่อนที่เครื่องใหม่นี้ ระบบจะจัดเก็บข้อมูลบางอย่างที่เกี่ยวข้องกับอุปกรณ์ Wear OS ไว้ในอุปกรณ์เคลื่อนที่ที่เชื่อมต่ออยู่ในปัจจุบัน

ตั้งแต่ Wear OS 4 เป็นต้นไป เมื่อเชื่อมต่อกับอุปกรณ์เคลื่อนที่เครื่องใหม่ ผู้ใช้จะโอนข้อมูล Wear OS ไปยังอุปกรณ์เคลื่อนที่เครื่องใหม่ได้ ระบบจะซิงค์ข้อมูลโดยอัตโนมัติเมื่อโอน

เมื่อผู้ใช้ส่งคำขอโอน เลเยอร์ข้อมูลอุปกรณ์ที่สวมใส่ได้จะส่งออบเจ็กต์ DataItem ซึ่งเดิมจัดเก็บไว้ในอุปกรณ์เคลื่อนที่เครื่องหนึ่งไปยังอุปกรณ์เคลื่อนที่อีกเครื่องหนึ่ง วิธีนี้ช่วยให้ผู้ใช้แอปได้รับประสบการณ์การใช้งานที่ราบรื่น

เอกสารนี้อธิบายวิธีกำหนดค่าแอป Wear OS และแอปที่ใช้ร่วมกันบนอุปกรณ์เคลื่อนที่ของแอปดังกล่าวเพื่อรองรับสถานการณ์นี้

การเตรียมพร้อม

กระบวนการโอนข้อมูลจะจัดการออบเจ็กต์ DataItem แตกต่างกันไป โดยขึ้นอยู่กับแอปที่เป็นเจ้าของข้อมูล

ออบเจ็กต์ที่แอป Wear OS เป็นเจ้าของ
ระบบจะเก็บออบเจ็กต์เหล่านี้ไว้ในอุปกรณ์ Wear OS
วัตถุที่แอปบนอุปกรณ์เคลื่อนที่เป็นเจ้าของ

ออบเจ็กต์เหล่านี้จะเก็บถาวรไว้ในอุปกรณ์เครื่องเก่า จากนั้นระบบจะแพ็กเกจข้อมูลที่เก็บถาวรเป็นออบเจ็กต์ DataItemBuffer และส่งข้อมูลนี้ไปยังแอปบนอุปกรณ์เคลื่อนที่ที่ติดตั้งในอุปกรณ์เคลื่อนที่เครื่องใหม่

ทันทีที่ส่งไฟล์เก็บถาวรแล้ว ชั้นข้อมูล Wearables จะเรียกใช้onNodeMigrated() listener ในลักษณะเดียวกับที่อุปกรณ์ Wear OS แจ้งเตือนแอปเมื่อเขียนข้อมูล

เก็บรักษาข้อมูลที่โอน

แอปของคุณมีหน้าที่รับผิดชอบในการรักษาออบเจ็กต์ DataItem ที่โอน ไม่นานหลังจากที่ส่งข้อมูลไปยังอุปกรณ์เคลื่อนที่เครื่องใหม่ ระบบจะลบที่เก็บถาวรออกจากอุปกรณ์เครื่องเก่า

ตรวจสอบว่าเงื่อนไขต่อไปนี้เป็นจริง

  1. แอปของคุณติดตั้งอยู่ในทั้ง 2 อุปกรณ์เคลื่อนที่ที่เกี่ยวข้องในการโอน
  2. แอปบนอุปกรณ์เคลื่อนที่ที่ติดตั้งในอุปกรณ์เคลื่อนที่แต่ละเครื่องมีลายเซ็นแพ็กเกจที่ตรงกัน

มิเช่นนั้น ระบบจะไม่นำส่งออบเจ็กต์ DataItem ที่เก็บถาวรและจะทิ้งออบเจ็กต์ดังกล่าว

รับข้อมูลจากอุปกรณ์เคลื่อนที่เครื่องเก่า

หากต้องการรับข้อมูลในอุปกรณ์เคลื่อนที่เครื่องใหม่ซึ่งเก็บถาวรไว้ในอุปกรณ์เคลื่อนที่เครื่องเก่า แอปบนอุปกรณ์เคลื่อนที่ของคุณต้องใช้การเรียกกลับ onNodeMigrated() ซึ่งเป็นส่วนหนึ่งของคลาส WearableListenerService โดยทำตามขั้นตอนต่อไปนี้

  1. ในไฟล์บิลด์ของแอปบนอุปกรณ์เคลื่อนที่ ให้ใส่การพึ่งพาไลบรารีอุปกรณ์ที่สวมใส่ได้เวอร์ชันล่าสุดในบริการ Google Play ดังนี้

    dependencies {
        ...
        implementation 'com.google.android.gms:play-services-wearable:19.0.0'
    }
  2. ประกาศและส่งออก WearableListenerService ในไฟล์ Manifest ของแอป

    <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()

    เพื่อรักษาทรัพยากรของระบบ เช่น อายุการใช้งานแบตเตอรี่ และเพื่อป้องกัน ANR

    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.
        }
    }