Memulai

Halaman ini menunjukkan cara menyiapkan lingkungan dan membuat Slice di aplikasi Anda.

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

  • Alat pemfaktoran ulang AndroidX: diperlukan jika Anda bekerja dalam project yang menggunakan library AndroidX.
  • Pemeriksaan lint Slice: mengenali anti-praktik umum saat membuat Slice
  • SliceProvidertemplate: menangani boilerplate saat membuat SliceProvider

Mendownload dan menginstal Slice Viewer

Download contoh terbaru rilis APK Slice Viewer yang dapat Anda gunakan untuk menguji Slice Anda tanpa mengimplementasikan SliceView API.

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 dalam 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 WiFi Slice tunggal

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 alat 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. 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 mengubah 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"

Membuat Slice pertama Anda

Untuk membuat 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.

Perubahan pada AndroidManifest.xml ditunjukkan seperti berikut:

<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. Saat ingin menampilkan Slice, permukaan akan mengirimkan permintaan binding ke aplikasi Anda dengan URI ini. Aplikasi Anda kemudian akan menangani permintaan ini dan secara dinamis membuat Slice melalui metode onBindSlice. Kemudian, surface dapat menampilkan Slice jika sesuai.

Berikut 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 berikut 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 input 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."
                }
            }
        }
    }
}

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