Sinkronkan data persisten

Dokumen ini menjelaskan cara menyinkronkan data antara perangkat Wear OS dan perangkat genggam.

Mengirim dan menyinkronkan data langsung dari jaringan

Bangun aplikasi Wear OS untuk berkomunikasi langsung dengan jaringan. Gunakan API yang sama dengan yang Anda gunakan untuk pengembangan seluler, tetapi perhatikan beberapa perbedaan khusus Wear OS.

Menyinkronkan data menggunakan Data Layer API Wear OS

DataClient mengekspos API agar komponen dapat membaca atau menulis ke DataItem atau Asset.

Anda dapat menyetel item data dan aset saat tidak terhubung ke perangkat apa pun. Keduanya disinkronkan saat perangkat terhubung ke jaringan. Data ini bersifat pribadi untuk aplikasi Anda dan hanya dapat diakses oleh aplikasi Anda di perangkat lain.

  • DataItem disinkronkan di semua perangkat dalam jaringan Wear OS. Item data tersebut biasanya berukuran kecil.

  • Gunakan Asset untuk mentransfer objek yang lebih besar, seperti gambar. Sistem melacak aset mana yang telah ditransfer dan melakukan penghapusan duplikat secara otomatis.

Memproses peristiwa dalam layanan

Perluas class WearableListenerService. Sistem mengelola siklus proses WearableListenerService dasar, melakukan binding ke layanan saat perlu mengirim item data atau pesan, dan membatalkan binding layanan ketika tidak diperlukan pekerjaan.

Memproses peristiwa dalam aktivitas

Terapkan antarmuka OnDataChangedListener. Gunakan antarmuka ini, bukan WearableListenerService, jika Anda ingin memproses perubahan, hanya ketika pengguna aktif menggunakan aplikasi Anda.

Mentransfer data

Untuk mengirim objek besar biner melalui transportasi Bluetooth, seperti rekaman suara dari perangkat lain, Anda dapat melampirkan Asset ke item data, lalu menempatkan item data ke dalam datastore replika.

Aset secara otomatis menangani caching data untuk mencegah transmisi ulang dan menghemat bandwidth Bluetooth. Pola umum ditujukan bagi aplikasi perangkat genggam untuk mendownload gambar, memperkecil ke ukuran yang sesuai untuk tampilan di perangkat wearable, dan mentransmisikan ke perangkat wearable sebagai aset. Contoh berikut mendemonstrasikan pola tersebut.

Catatan: Meskipun secara teoritis ukuran item data dibatasi hingga 100 KB, pada praktiknya, item data yang lebih besar dapat digunakan. Untuk item data yang lebih besar, pisahkan data berdasarkan jalur unik dan hindari penggunaan satu jalur untuk semua data. Mentransfer aset besar akan memengaruhi pengalaman pengguna dalam banyak kasus. Jadi, uji aplikasi Anda untuk membantu memastikan aplikasi dapat berperforma baik saat mentransfer aset besar.

Mentransfer aset

Buat aset menggunakan salah satu metode create...() dalam class Asset. Konversi bitmap ke aliran byte, lalu panggil createFromBytes() untuk membuat aset, seperti ditunjukkan pada contoh berikut.

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

Selanjutnya, lampirkan aset ke item data dengan metode putAsset() di DataMap atau PutDataRequest. Lalu, masukkan item data ke dalam datastore menggunakan metode putDataItem(), seperti ditunjukkan dalam contoh berikut.

Contoh berikut menggunakan 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);

Contoh berikut menggunakan 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);

Menerima aset

Ketika aset dibuat, Anda mungkin ingin membaca dan mengekstraknya di sisi lain koneksi. Berikut adalah contoh cara menerapkan callback untuk mendeteksi perubahan aset dan mengekstrak aset:

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);
}

Untuk mengetahui informasi selengkapnya, lihat project contoh DataLayer di GitHub.