Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Mengekspos data ke detail

Aplikasi penyedia data menampilkan informasi ke detail tampilan jam, yang menyediakan kolom berisi teks, string, gambar, dan angka.

Layanan penyedia data memperluas ComplicationProviderService untuk menayangkan informasi yang berguna ke tampilan jam secara langsung.

Membuat project penyedia data

Untuk membuat project di Android Studio bagi aplikasi penyedia data Anda:

  1. Klik File > New > New project.
  2. Di jendela Create Project Android, terima nilai default, lalu klik Next.
  3. Di jendela Target Android Devices, pilih hanya opsi Wear, dan pada daftar versi SDK, pilih versi terbaru yang tersedia. Klik Next.
  4. Di jendela Add an Activity to Wear, pilih Add No Activity, lalu klik Finish.

    Android Studio akan membuat project dengan modul app untuk penyedia data Anda. Untuk informasi selengkapnya tentang project di Android Studio, lihat Membuat Project.

  5. Mulai aplikasi penyedia data Anda dengan membuat class baru yang memperluas BroadcastReceiver. Fungsi class tersebut adalah memantau permintaan update detail dari sistem Wear OS. Selain itu, buat class baru yang memperluas ComplicationProviderService untuk benar-benar menyediakan data seperti yang diminta oleh detail yang terkait. Untuk informasi selengkapnya, lihat referensi berikut:

    Catatan: Menambahkan aktivitas untuk penyedia data bersifat opsional. Misalnya, Anda mungkin ingin menambahkan aktivitas yang hanya diluncurkan ketika pengguna mengetuk suatu detail.

Mengimplementasikan metode untuk permintaan update

Ketika data detail diperlukan, sistem Wear OS akan mengirimkan permintaan update ke penyedia data Anda. Permintaan tersebut diterima oleh BroadcastReceiver. Untuk menanggapi permintaan update tersebut, penyedia data harus mengimplementasikan metode onComplicationUpdate() dari class ComplicationProviderService. Sistem Wear OS memanggil metode ini ketika data diperlukan dari penyedia Anda, misalnya ketika detail yang menggunakan penyedia Anda menjadi aktif, atau ketika jumlah waktu yang ditentukan telah terlewati. Objek ComplicationManager diteruskan sebagai parameter ke metode onComplicationUpdate, dan dapat digunakan untuk mengirimkan data kembali ke sistem.

Catatan: Ketika aplikasi penyedia data menyediakan data, tampilan jam akan menerima nilai mentah yang Anda kirimkan sehingga dapat mengambil informasinya.

Cuplikan kode berikut menunjukkan contoh implementasi metode onComplicationUpdate:

Kotlin

    override fun onComplicationUpdate(
        complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

        Log.d(TAG, "onComplicationUpdate() id: $complicationId")

        // Used to create a unique key to use with SharedPreferences for this complication.
        val thisProvider = ComponentName(this, javaClass)

        // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
        val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

        val number = preferences.getInt(
                ComplicationTapBroadcastReceiver.getPreferenceKey(
                        thisProvider, complicationId),
                        0)
        val numberText = String.format(Locale.getDefault(), "%d!", number)

        var complicationData: ComplicationData? = null

        when (dataType) {
            ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                    .setShortText(ComplicationText.plainText(numberText))
                    .build()
            else -> if (Log.isLoggable(TAG, Log.WARN)) {
                        Log.w(TAG, "Unexpected complication type $dataType")
                    }
        }

        if (complicationData != null) {
            complicationManager.updateComplicationData(complicationId, complicationData)
        } else {
            // If no data is sent, we still need to inform the ComplicationManager, so
            // the update job can finish and the wake lock isn't held any longer.
            complicationManager.noUpdateRequired(complicationId)
        }
    }
    

Java

    @Override
    public void onComplicationUpdate(
           int complicationId, int dataType, ComplicationManager complicationManager) {

       Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

       // Used to create a unique key to use with SharedPreferences for this complication.
       ComponentName thisProvider = new ComponentName(this, getClass());

       // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
       SharedPreferences preferences =
         getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

       int number =
               preferences.getInt(
                       ComplicationTapBroadcastReceiver.getPreferenceKey(
                               thisProvider, complicationId),
                       0);
       String numberText = String.format(Locale.getDefault(), "%d!", number);

       ComplicationData complicationData = null;

       switch (dataType) {
           case ComplicationData.TYPE_SHORT_TEXT:
               complicationData =
                       new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                               .setShortText(ComplicationText.plainText(numberText))
                               .build();
               break;
           default:
               if (Log.isLoggable(TAG, Log.WARN)) {
                   Log.w(TAG, "Unexpected complication type " + dataType);
               }
       }

       if (complicationData != null) {
           complicationManager.updateComplicationData(complicationId, complicationData);

       } else {
           // If no data is sent, we still need to inform the ComplicationManager, so
           // the update job can finish and the wake lock isn't held any longer.
           complicationManager.noUpdateRequired(complicationId);
       }
    }
    

Izin dan deklarasi manifes

Aplikasi penyedia data harus menyertakan deklarasi spesifik dalam manifes aplikasinya agar diperlakukan sebagai penyedia data oleh sistem Android. Bagian ini menjelaskan setelan yang diperlukan untuk aplikasi penyedia data. Dalam manifes aplikasi Anda, deklarasikan layanan dan tambahkan filter intent tindakan permintaan update. Manifes juga harus melindungi layanan dengan menambahkan izin BIND_COMPLICATION_PROVIDER untuk memastikan bahwa hanya sistem Wear OS yang dapat terikat ke layanan penyedia.

Selain itu, dalam elemen layanan, Anda harus menyertakan atribut android:icon. Ikon yang disediakan harus berupa ikon putih berwarna tunggal. Drawable vektor direkomendasikan untuk ikon tersebut. Ikon harus mewakili penyedia dan akan ditampilkan dalam pemilih penyedia.

Berikut ini contohnya:

    <service
        android:name=".provider.IncrementingNumberComplicationProviderService"
        android:icon="@drawable/icn_complications"
        android:label="@string/complications_provider_incrementing_number"
        android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
        <intent-filter>
            <action
             android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
        </intent-filter>
    </service>
    

Menetapkan elemen metadata

Dalam file manifes Anda, sertakan metadata untuk menentukan jenis yang didukung, periode update, dan tindakan konfigurasi seperti yang ditunjukkan dalam contoh berikut:

    <meta-data
        android:name="android.support.wearable.complications.SUPPORTED_TYPES"
        android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

    <meta-data
        android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
        android:value="300" />
    

Ketika penyedia data detail Anda aktif, UPDATE_PERIOD_SECONDS akan menentukan seberapa sering sistem perlu memeriksa update data. Jika informasi yang ditampilkan dalam detail tidak perlu diupdate secara rutin, seperti ketika Anda menggunakan update push, tetapkan nilai ini ke 0.

Jika UPDATE_PERIOD_SECONDS tidak ditetapkan ke 0, Anda harus menggunakan nilai minimal 300 (5 menit), yaitu periode update minimal yang diberlakukan sistem agar masa pakai baterai perangkat lebih tahan lama. Selain itu, perlu diingat bahwa permintaan update mungkin muncul lebih jarang ketika perangkat berada dalam mode standby atau sedang tidak dipakai.

Untuk detail selengkapnya tentang mengirimkan update, lihat kunci yang tersedia untuk class ComplicationProviderService dalam Referensi Wear API.

Menambahkan aktivitas konfigurasi

Jika diperlukan, penyedia dapat menyertakan aktivitas konfigurasi yang ditampilkan kepada pengguna ketika memilih penyedia data. Untuk menyertakan aktivitas konfigurasi, sertakan item metadata pada deklarasi layanan penyedia dalam manifes dengan kunci berikut:

    <meta-data
        android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
        android:value="PROVIDER_CONFIG_ACTION"/>
    

Nilai dapat berupa tindakan yang Anda inginkan.

Kemudian, buat aktivitas konfigurasi dengan filter intent untuk tindakan tersebut. Aktivitas konfigurasi harus berada dalam paket yang sama dengan penyedia. Aktivitas konfigurasi harus menghasilkan RESULT_OK atau RESULT_CANCELED untuk memberi tahu sistem apakah penyedia harus ditetapkan.

Tampilan jam aman yang ditetapkan penyedia

Penyedia dapat menentukan tampilan jam tertentu sebagai "aman" untuk menerima data mereka. Sebaiknya, hanya lakukan hal ini ketika tampilan jam mencoba menggunakan penyedia tersebut sebagai penyedia default (lihat di bawah ini), dan penyedia memercayai aplikasi tampilan jam.

Untuk mendeklarasikan tampilan jam sebagai aman, penyedia akan menambahkan metadata dengan kunci android.support.wearable.complications.SAFE_WATCH_FACES. Nilai metadata harus berupa daftar yang dipisahkan koma (spasi kosong akan diabaikan). Entri dalam daftar dapat berupa nama komponen (dari WatchFaceServices, diberikan seolah-olah ComponentName.flattenToString() telah dipanggil), atau dapat berupa nama paket (dari aplikasi, dalam situasi ketika setiap tampilan jam dalam aplikasi tertentu dianggap aman). Contoh:

    <meta-data
           android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
           android:value="
              com.app.watchface/com.app.watchface.MyWatchFaceService,
              com.anotherapp.anotherwatchface/com.something.WatchFaceService,
              com.something.text"/>
    

Menyediakan gambar bebas burn-in

Di layar yang rentan terhadap burn-in, blok warna solid harus dihindari dalam mode standby. Jika ikon atau gambar Anda menyertakan blok warna solid, Anda juga harus menyediakan versi bebas burn-in.

Saat Anda menyediakan ikon menggunakan ComplicationData.Builder#setIcon, sertakan versi yang bebas burn-in menggunakan ComplicationData.Builder#setBurnInProtectionIcon.

Ketika Anda memberikan gambar menggunakan ComplicationData.Builder#setSmallImage, sertakan versi yang bebas burn-in menggunakan ComplicationData.Builder#setBurnInProtectionSmallImage.

Menggunakan update push

Selain menentukan interval update yang konstan dan tidak nol untuk detail dalam manifes aplikasi, Anda dapat menggunakan instance ProviderUpdateRequester untuk meminta update secara dinamis. Untuk meminta update ke konten detail yang dapat dilihat pengguna, panggil onComplicationUpdate().

Perhatian: Untuk mempertahankan masa pakai baterai perangkat, instance ProviderUpdateRequester tidak boleh memanggil onComplicationUpdate() lebih sering dari rata-rata 5 menit sekali.

Menyediakan nilai-nilai yang bergantung pada waktu

Beberapa detail perlu menampilkan nilai yang berhubungan dengan waktu saat ini. Contohnya termasuk tanggal saat ini, waktu hingga pertemuan berikutnya, atau waktu di zona waktu lain.

Jangan mengupdate detail setiap detik atau menit agar nilainya selalu terkini; detail seharusnya tidak perlu diupdate sesering itu. Sebagai gantinya, tetapkan nilai sebagai nilai yang relatif terhadap tanggal atau waktu saat ini menggunakan teks yang bergantung pada waktu. Anda dapat menggunakan builder dalam class ComplicationText untuk membuat nilai yang bergantung pada waktu ini.