Bắt đầu

Trang này cho bạn biết cách thiết lập môi trường và tạo Lát cắt trong ứng dụng.

Lưu ý: Android Studio 3.2 trở lên có chứa các công cụ và chức năng bổ sung có thể giúp bạn phát triển Lát cắt:

  • Công cụ tái cấu trúc AndroidX: bắt buộc nếu bạn đang làm việc trong một dự án sử dụng các thư viện AndroidX.
  • Kiểm tra tìm lỗi mã nguồn cho Lát cắt: phát hiện các phương pháp chống lại phổ biến khi tạo Lát cắt
  • Mẫu SliceProvider: xử lý mẫu nguyên mẫu khi tạo SliceProvider

Tải và cài đặt Trình xem Lát cắt

Tải bản phát hành APK Trình xem Lát cắt mẫu mới nhất xuống để kiểm thử Lát cắt mà không cần triển khai API SliceView.

Nếu ADB không được thiết lập đúng cách trong môi trường của bạn, hãy xem hướng dẫn về ADB để biết thêm thông tin.

Cài đặt Trình xem lát cắt trên thiết bị của bạn bằng cách chạy lệnh sau trong cùng thư mục với slice-viewer.apk đã tải xuống:

adb install -r -t slice-viewer.apk

Chạy Trình xem Lát cắt

Bạn có thể chạy Trình xem lát cắt từ dự án Android Studio hoặc qua dòng lệnh:

Chạy Trình xem lát cắt trong dự án Android Studio

  1. Trong dự án, hãy chọn Run > Edit Configurations... (Chạy > Chỉnh sửa cấu hình...)
  2. Ở góc trên cùng bên trái, hãy nhấp vào dấu cộng màu xanh lục
  3. Chọn Ứng dụng Android

  4. Nhập Lát cắt vào trường tên

  5. Chọn mô-đun ứng dụng của bạn trong trình đơn thả xuống Module (Mô-đun)

  6. Trong Tuỳ chọn khởi chạy, chọn URL từ trình đơn thả xuống Khởi chạy

  7. Nhập slice-<your slice URI> vào trường URL

    Ví dụ: slice-content://com.example.your.sliceuri

  8. Nhấp vào OK

Chạy công cụ Trình xem lát cắt thông qua ADB (dòng lệnh)

Chạy ứng dụng trong Android Studio:

adb install -t -r <yourapp>.apk

Xem Lát cắt của bạn bằng cách chạy lệnh sau:

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

Trình xem Lát cắt hiển thị một Lát cắt Wi-Fi

Xem tất cả Lát cắt ở cùng một nơi

Ngoài việc khởi chạy một Lát cắt, bạn có thể xem danh sách cố định các Lát cắt của mình.

  • Sử dụng thanh tìm kiếm để tìm kiếm Lát cắt theo cách thủ công thông qua URI (ví dụ: content://com.example.android.app/hello). Mỗi lần bạn tìm kiếm, Lát cắt sẽ được thêm vào danh sách.
  • Bất cứ khi nào bạn chạy công cụ Trình xem Lát cắt có URI Lát cắt, Lát cắt sẽ được thêm vào danh sách.
  • Bạn có thể vuốt một Lát cắt để xoá nó khỏi danh sách.
  • Nhấn vào URI của Lát cắt để xem trang chỉ chứa Lát cắt đó. Việc này có tác dụng tương tự như việc chạy Slice Viewer bằng URI Slice (Lát cắt).

Trình xem Lát cắt hiển thị danh sách Lát cắt

Xem Lát cắt ở nhiều chế độ

Ứng dụng thể hiện một Lát cắt có thể sửa đổi SliceView#mode trong thời gian chạy. Vì vậy, bạn phải đảm bảo Lát cắt của mình trông như dự kiến ở mỗi chế độ. Chọn biểu tượng trình đơn ở khu vực trên cùng bên phải của trang để thay đổi chế độ.

Trình xem một Lát cắt với chế độ được đặt thành "nhỏ"

Tạo Lát cắt đầu tiên

Để tạo một Lát cắt, hãy mở dự án Android Studio, nhấp chuột phải vào gói src rồi chọn New... > Khác > Trình cung cấp lát cắt. Thao tác này sẽ tạo một lớp mở rộng SliceProvider, thêm mục nhập của trình cung cấp bắt buộc vào AndroidManifest.xml và sửa đổi build.gradle để thêm các phần phụ thuộc Lát cắt bắt buộc.

Dưới đây là nội dung sửa đổi đối với AndroidManifest.xml:

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

Các phần phụ thuộc sau đây được thêm vào build.gradle của bạn:

Kotlin

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

Java

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

Mỗi Lát cắt đều có một URI liên kết. Khi muốn hiển thị một Lát cắt, nền tảng đó sẽ gửi yêu cầu liên kết đến ứng dụng của bạn qua URI này. Sau đó, ứng dụng của bạn sẽ xử lý yêu cầu này và tự động tạo Lát cắt thông qua phương thức onBindSlice. Sau đó, bề mặt có thể hiển thị Lát cắt khi thích hợp.

Dưới đây là ví dụ về phương thức onBindSlice kiểm tra đường dẫn URI /hello và trả về một Lát cắt 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();
}

Sử dụng cấu hình chạy Lát cắt mà bạn đã tạo trong phần Trình xem Lát cắt ở trên, truyền vào URI Lát cắt (ví dụ: slice-content://com.android.example.slicesample/hello) của Lát cắt Hello World để xem trong Trình xem Lát cắt.

Lát cắt tương tác

Tương tự như thông báo, bạn có thể xử lý các lượt nhấp trong Lát cắt bằng cách đính kèm các đối tượng PendingIntent được kích hoạt khi người dùng tương tác. Ví dụ bên dưới bắt đầu một Activity có thể nhận và xử lý các ý định đó:

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

Lát cắt cũng hỗ trợ các loại dữ liệu đầu vào khác (chẳng hạn như nút bật/tắt) trong đó có trạng thái trong ý định được gửi đến ứng dụng.

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

Sau đó, người nhận có thể kiểm tra trạng thái nhận được:

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

Lát cắt động

Lát cắt cũng có thể chứa nội dung động. Trong ví dụ sau, Lát cắt hiện bao gồm số lượng thông báo truyền tin nhận được trong nội dung:

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

Trong ví dụ này, mặc dù số lượng được hiển thị, nhưng nó không tự cập nhật. Bạn có thể sửa đổi broadcast receiver để thông báo cho hệ thống rằng đã xảy ra thay đổi bằng cách sử dụng 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);
        }
    }
}

Mẫu

Lát cắt hỗ trợ nhiều mẫu. Để biết thêm thông tin chi tiết về các lựa chọn và hành vi của mẫu, hãy xem phần Mẫu.