Memulai

Halaman ini menunjukkan cara menyiapkan lingkungan dan mem-build Slice di aplikasi Anda.

Catatan: Android Studio 3.2 atau yang lebih baru berisi fitur dan fungsi tambahan yang dapat membantu Anda dalam pengembangan Slice:

  • Fitur pemfaktoran ulang AndroidX: diperlukan jika Anda bekerja dalam project yang menggunakan library AndroidX.
  • Pemeriksaan lint Slice: menangkap anti-praktik umum saat mem-build Slices
  • SliceProvidertemplate: menangani boilerplate saat mem-build

Mendownload dan menginstal Slice Viewer

Download contoh terbaru rilis APK Slice Viewer yang dapat Anda gunakan untuk menguji Slice tanpa menerapkan SliceView API. Anda juga dapat menduplikat sumber Slice Viewer.

Jika ADB tidak disiapkan dengan benar di lingkungan Anda, lihat panduan ADB untuk informasi selengkapnya.

Instal Slice Viewer di perangkat Anda dengan menjalankan perintah berikut dalam direktori yang sama seperti slice-viewer.apk yang didownload:

adb install -r -t slice-viewer.apk
    

Menjalankan Slice Viewer

Anda dapat meluncurkan Slice Viewer dari project Android Studio atau command line:

Meluncurkan Slice Viewer dari project Android Studio Anda

  1. Dalam project Anda, pilih Jalankan > Edit Konfigurasi...
  2. Di sudut kiri atas, klik tanda plus berwarna hijau
  3. Pilih Aplikasi Android

  4. Masukkan slice di kolom nama

  5. Pilih modul aplikasi Anda pada dropdown Modul

  6. Pada Opsi Peluncuran, pilih URL dari dropdown Luncurkan

  7. Masukkan slice-<your slice URI> dalam kolom URL

    Contoh: slice-content://com.example.your.sliceuri

  8. Klik OKE.

Meluncurkan fitur Slice Viewer melalui ADB (command line)

Jalankan aplikasi Anda dari Android Studio:

adb install -t -r <yourapp>.apk
    

Lihat Slice Anda dengan menjalankan perintah berikut:

adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>
    

Slice Viewer yang menampilkan satu WiFi Slice

Melihat semua Slice Anda di satu tempat

Selain meluncurkan Slice tunggal, Anda dapat melihat daftar tetap Slice Anda.

  • Gunakan kotak penelusuran untuk menelusuri Slice melalui URI secara manual (contohnya, content://com.example.android.app/hello). Setiap kali Anda menelusuri, Slice akan ditambahkan ke daftar.
  • Kapan pun Anda meluncurkan fitur Slice Viewer dengan URI Slice, Slice akan ditambahkan ke daftar.
  • Anda dapat menggeser Slice untuk menghapusnya dari daftar.
  • Ketuk URI Slice untuk melihat halaman yang hanya berisi Slice tersebut. Hal ini memiliki efek yang sama seperti meluncurkan Slice Viewer dengan URI Slice.

Slice Viewer yang menampilkan daftar Slice

Melihat Slice dalam mode yang berbeda

Aplikasi yang menyajikan Slice dapat memodifikasi SliceView#mode pada waktu proses, sehingga Anda harus memastikan bahwa Slice terlihat seperti yang diharapkan dalam setiap mode. Pilih ikon menu di bagian kanan atas halaman untuk mengubah mode.

Slice viewer tunggal dengan mode yang disetel ke "kecil"

Mem-build Slice pertama Anda

Untuk mem-build Slice, buka project Android Studio, klik kanan paket src, lalu pilih Baru... > Lainnya > Penyedia Slice. Ini akan membuat class yang memperluas SliceProvider, menambahkan entri penyedia yang diperlukan ke AndroidManifest.xml Anda, dan mengubah build.gradle untuk menambahkan dependensi Slice yang diperlukan.

Modifikasi ke AndroidManifest.xml ditunjukkan di bawah ini:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.android.app">
        ...
        <application>
            ...
            <provider android:name="MySliceProvider"
                android:authorities="com.example.android.app"
                android:exported="true" >
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.app.slice.category.SLICE" />
                </intent-filter>
            </provider>
            ...
        </application>

    </manifest>
    

Dependensi berikut ditambahkan ke build.gradle Anda:

Kotlin

    dependencies {
    // ...
        implementation "androidx.slice:slice-builders-ktx:(latest version)"
    // ...
    }
    

Java

    dependencies {
    // ...
        implementation "androidx.slice:slice-builders:(latest version)"
    // ...
    }
    

Setiap Slice memiliki URI terkait. Ketika ingin menampilkan Slice, surface akan mengirimkan permintaan binding ke aplikasi Anda dengan URI ini. Kemudian aplikasi Anda akan menangani permintaan ini dan secara dinamis mem-build Slice melalui metode onBindSlice. Kemudian, surface dapat menampilkan Slice bila sesuai.

Di bawah ini adalah contoh metode onBindSlice yang memeriksa jalur URI /hello dan menampilkan Slice Hello World:

Kotlin

    override fun onBindSlice(sliceUri: Uri): Slice? {
        val activityAction = createActivityAction()
        return if (sliceUri.path == "/hello") {
            list(context, sliceUri, ListBuilder.INFINITY) {
                row {
                    primaryAction = activityAction
                    title = "Hello World."
                }
            }
        } else {
            list(context, sliceUri, ListBuilder.INFINITY) {
                row {
                    primaryAction = activityAction
                    title = "URI not recognized."
                }
            }
        }
    }
    

Java

    @Override
    public Slice onBindSlice(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        SliceAction activityAction = createActivityAction();
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
        // Create parent ListBuilder.
        if ("/hello".equals(sliceUri.getPath())) {
            listBuilder.addRow(new ListBuilder.RowBuilder()
                    .setTitle("Hello World")
                    .setPrimaryAction(activityAction)
            );
        } else {
            listBuilder.addRow(new ListBuilder.RowBuilder()
                    .setTitle("URI not recognized")
                    .setPrimaryAction(activityAction)
            );
        }
        return listBuilder.build();
    }
    

Gunakan konfigurasi pengoperasian slice yang dibuat di bagian Slice Viewer di atas, yang meneruskan URI Slice Anda (misalnya, slice-content://com.android.example.slicesample/hello) dari Slice Hello World untuk melihatnya di Slice Viewer.

Slice Interaktif

Mirip dengan notifikasi, Anda dapat menangani klik dalam Slice dengan melampirkan objek PendingIntent yang dipicu pada interaksi pengguna. Contoh di bawah ini memulai Activity yang dapat menerima dan menangani intent tersebut:

Kotlin

    fun createSlice(sliceUri: Uri): Slice {
        val activityAction = createActivityAction()
        return list(context, sliceUri, INFINITY) {
            row {
                title = "Perform action in app"
                primaryAction = activityAction
            }
        }
    }

    fun createActivityAction(): SliceAction {
        val intent = Intent(context, MainActivity::class.java)
        return SliceAction.create(
            PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), 0),
            IconCompat.createWithResource(context, R.drawable.ic_home),
            ListBuilder.ICON_IMAGE,
            "Enter app"
        )
    }
    

Java

    public Slice createSlice(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        SliceAction activityAction = createActivityAction();
        return new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .addRow(new ListBuilder.RowBuilder()
                        .setTitle("Perform action in app.")
                        .setPrimaryAction(activityAction)
                ).build();
    }

    public SliceAction createActivityAction() {
        if (getContext() == null) {
            return null;
        }
        return SliceAction.create(
                PendingIntent.getActivity(
                        getContext(),
                        0,
                        new Intent(getContext(), MainActivity.class),
                        0
                ),
                IconCompat.createWithResource(getContext(), R.drawable.ic_home),
                ListBuilder.ICON_IMAGE,
                "Enter app"
        );
    }
    

Slice juga mendukung jenis masukan lain, seperti tombol, yang mencakup status dalam intent yang dikirim ke aplikasi.

Kotlin

    fun createBrightnessSlice(sliceUri: Uri): Slice {
        val toggleAction =
            SliceAction.createToggle(
                createToggleIntent(),
                "Toggle adaptive brightness",
                true
            )
        return list(context, sliceUri, ListBuilder.INFINITY) {
            row {
                title = "Adaptive brightness"
                subtitle = "Optimizes brightness for available light"
                primaryAction = toggleAction
            }
            inputRange {
                inputAction = (brightnessPendingIntent)
                max = 100
                value = 45
            }
        }
    }

    fun createToggleIntent(): PendingIntent {
        val intent = Intent(context, MyBroadcastReceiver::class.java)
        return PendingIntent.getBroadcast(context, 0, intent, 0)
    }
    

Java

    public Slice createBrightnessSlice(Uri sliceUri) {
        if (getContext() == null) {
            return null;
        }
        SliceAction toggleAction = SliceAction.createToggle(
                createToggleIntent(),
                "Toggle adaptive brightness",
                true
        );
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY)
                .addRow(new ListBuilder.RowBuilder()
                        .setTitle("Adaptive brightness")
                        .setSubtitle("Optimizes brightness for available light.")
                        .setPrimaryAction(toggleAction)
                ).addInputRange(new ListBuilder.InputRangeBuilder()
                        .setInputAction(brightnessPendingIntent)
                        .setMax(100)
                        .setValue(45)
                );
        return listBuilder.build();
    }

    public PendingIntent createToggleIntent() {
        Intent intent = new Intent(getContext(), MyBroadcastReceiver.class);
        return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
    }
    

Penerima kemudian dapat memeriksa status yang diterima:

Kotlin

    class MyBroadcastReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) {
                Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                        Slice.EXTRA_TOGGLE_STATE, false),
                        Toast.LENGTH_LONG).show()
            }
        }

        companion object {
            const val EXTRA_MESSAGE = "message"
        }
    }
    

Java

    public class MyBroadcastReceiver extends BroadcastReceiver {

        public static String EXTRA_MESSAGE = "message";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
                Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                        EXTRA_TOGGLE_STATE, false),
                        Toast.LENGTH_LONG).show();
            }
        }
    }
    

Slice Dinamis

Slice juga dapat berisi konten dinamis. Pada contoh berikut, Slice sekarang menyertakan jumlah siaran yang diterima dalam kontennya:

Kotlin

    fun createDynamicSlice(sliceUri: Uri): Slice {
        return when (sliceUri.path) {
            "/count" -> {
                val toastAndIncrementAction = SliceAction.create(
                    createToastAndIncrementIntent("Item clicked."),
                    actionIcon,
                    ListBuilder.ICON_IMAGE,
                    "Increment."
                )
                list(context, sliceUri, ListBuilder.INFINITY) {
                    row {
                        primaryAction = toastAndIncrementAction
                        title = "Count: ${MyBroadcastReceiver.receivedCount}"
                        subtitle = "Click me"
                    }
                }
            }

            else -> {
                list(context, sliceUri, ListBuilder.INFINITY) {
                    row {
                        primaryAction = createActivityAction()
                        title = "URI not found."
                    }
                }
            }
        }
    }

    fun createToastAndIncrementIntent(s: String): PendingIntent {
        return PendingIntent.getBroadcast(
            context, 0,
            Intent(context, MyBroadcastReceiver::class.java)
                .putExtra(MyBroadcastReceiver.EXTRA_MESSAGE, s), 0
        )
    }
    

Java

    public Slice createDynamicSlice(Uri sliceUri) {
        if (getContext() == null || sliceUri.getPath() == null) {
            return null;
        }
        ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, ListBuilder.INFINITY);
        switch (sliceUri.getPath()) {
            case "/count":
                SliceAction toastAndIncrementAction = SliceAction.create(
                        createToastAndIncrementIntent("Item clicked."),
                        actionIcon,
                        ListBuilder.ICON_IMAGE,
                        "Increment."
                );
                listBuilder.addRow(
                        new ListBuilder.RowBuilder()
                                .setPrimaryAction(toastAndIncrementAction)
                                .setTitle("Count: " + MyBroadcastReceiver.sReceivedCount)
                                .setSubtitle("Click me")
                );
                break;
            default:
                listBuilder.addRow(
                        new ListBuilder.RowBuilder()
                                .setPrimaryAction(createActivityAction())
                                .setTitle("URI not found.")
                );
                break;
        }
        return listBuilder.build();
    }

    public PendingIntent createToastAndIncrementIntent(String s) {
        Intent intent = new Intent(getContext(), MyBroadcastReceiver.class)
                .putExtra(MyBroadcastReceiver.EXTRA_MESSAGE, s);
        return PendingIntent.getBroadcast(getContext(), 0, intent, 0);
    }
    

Dalam contoh ini, saat jumlah ditampilkan, data tidak diupdate dengan sendirinya. Anda dapat memodifikasi penerima siaran untuk memberi tahu sistem bahwa telah terjadi perubahan menggunakan ContentResolver#notifyChange.

Kotlin

    class MyBroadcastReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            if (intent.hasExtra(Slice.EXTRA_TOGGLE_STATE)) {
                Toast.makeText(
                    context, "Toggled:  " + intent.getBooleanExtra(
                        Slice.EXTRA_TOGGLE_STATE, false
                    ),
                    Toast.LENGTH_LONG
                ).show()
                receivedCount++;
                context.contentResolver.notifyChange(sliceUri, null)
            }
        }

        companion object {
            var receivedCount = 0
            val sliceUri = Uri.parse("content://com.android.example.slicesample/count")
            const val EXTRA_MESSAGE = "message"
        }
    }
    

Java

    public class MyBroadcastReceiver extends BroadcastReceiver {

        public static int sReceivedCount = 0;
        public static String EXTRA_MESSAGE = "message";

        private static Uri sliceUri = Uri.parse("content://com.android.example.slicesample/count");

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.hasExtra(EXTRA_TOGGLE_STATE)) {
                Toast.makeText(context, "Toggled:  " + intent.getBooleanExtra(
                        EXTRA_TOGGLE_STATE, false),
                        Toast.LENGTH_LONG).show();
                sReceivedCount++;
                context.getContentResolver().notifyChange(sliceUri, null);
            }
        }
    }
    

Template

Slices mendukung berbagai template. Untuk detail selengkapnya tentang opsi dan perilaku template, lihat Template.