หน้านี้จะแสดงวิธีตั้งค่าสภาพแวดล้อมและบิลด์ ส่วนแบ่งในแอป
หมายเหตุ: Android Studio 3.2 ขึ้นไปมี เครื่องมือและฟังก์ชันที่จะช่วยคุณพัฒนา Slice ได้
- เครื่องมือเปลี่ยนโครงสร้างภายในโค้ด AndroidX: จำเป็นหากคุณกำลังทำงานในโปรเจ็กต์ที่ ใช้ไลบรารี AndroidX
- Slices Lint Check: พบแนวทางปฏิบัติทั่วไปในการต่อต้านเมื่อสร้าง แบ่งเป็นช่องๆ
- เทมเพลต
SliceProvider
: จัดการต้นแบบเมื่อ การสร้างSliceProvider
ดาวน์โหลดและติดตั้ง Slice Viewer
ดาวน์โหลดตัวอย่างล่าสุด
รุ่น APK ของ Slice Viewer
ที่คุณสามารถใช้เพื่อทดสอบ Slice โดยไม่ต้องติดตั้ง
SliceView
API
หาก ADB ไม่ได้รับการตั้งค่าอย่างถูกต้องในสภาพแวดล้อมของคุณ โปรดดู ดูข้อมูลเพิ่มเติมได้ที่คู่มือ AADB
ติดตั้ง Slice Viewer บนอุปกรณ์ของคุณโดยเรียกใช้คำสั่งต่อไปนี้ใน
ไดเรกทอรีเดียวกันกับ slice-viewer.apk
ที่ดาวน์โหลดไว้:
adb install -r -t slice-viewer.apk
เรียกใช้โปรแกรมดู Slice
คุณเปิดใช้ Slice Viewer จากโปรเจ็กต์ Android Studio หรือจาก บรรทัดคำสั่งดังนี้
เปิด Slice Viewer จากโปรเจ็กต์ Android Studio ของคุณ
- เลือก Run > (เรียกใช้) ในโปรเจ็กต์ แก้ไขการกำหนดค่า...
- คลิกเครื่องหมายบวกสีเขียวที่มุมซ้ายบน
เลือกแอป Android
ป้อนส่วนแบ่งในช่องชื่อ
เลือกโมดูลแอปในเมนูแบบเลื่อนลงโมดูล
ในส่วนตัวเลือกการเปิดตัว ให้เลือก URL จากเมนูแบบเลื่อนลงการเปิดตัว
ป้อน
slice-<your slice URI>
ในช่อง URLตัวอย่าง:
slice-content://com.example.your.sliceuri
คลิกตกลง
เปิดเครื่องมือ Slice Viewer ผ่าน ADB (บรรทัดคำสั่ง)
เรียกใช้แอปจาก Android Studio โดยทำดังนี้
adb install -t -r <yourapp>.apk
ดู Slice โดยเรียกใช้คำสั่งต่อไปนี้
adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>
Slice Viewer ที่แสดงเครือข่าย Wi-Fi เดี่ยว
ดูส่วนแบ่งทั้งหมดของคุณในที่เดียว
นอกจากการเปิดตัวเพียงส่วนเดียวแล้ว คุณยังสามารถดูรายการถาวรของ แบ่งช่อง
- ใช้แถบค้นหาเพื่อค้นหาสไลซ์ของคุณผ่าน URI ด้วยตนเอง (เช่น
content://com.example.android.app/hello
) ทุกครั้งที่คุณค้นหา Slice เพิ่มลงในรายการแล้ว - เมื่อใดก็ตามที่คุณเปิดเครื่องมือดูส่วนแบ่งด้วย URI ส่วนแบ่ง ระบบจะเพิ่มส่วนแบ่งดังกล่าว ลงในรายการ
- คุณสามารถปัดสไลซ์เพื่อนำออกจากรายการ
- แตะ URI ของส่วนเพื่อดูหน้าเว็บที่มีเฉพาะสไลซ์ดังกล่าว มี ซึ่งจะส่งผลเหมือนกับการเปิด Slice Viewer ด้วย URI Slice
Slice Viewer ที่แสดงรายการสไลซ์
ดูสไลซ์ในโหมดต่างๆ
แอปที่นำเสนอสไลซ์สามารถแก้ไข
SliceView#mode
ขณะรันไทม์ ดังนั้นคุณควรตรวจสอบว่า Slice มีลักษณะตามที่คาดไว้ในแต่ละโหมด
เลือกไอคอนเมนูที่บริเวณด้านขวาบนของหน้าเพื่อเปลี่ยนโหมด
โปรแกรมดูส่วนแบ่งเดี่ยวที่ตั้งค่าโหมดเป็น "เล็ก"
สร้าง Slice แรกของคุณ
หากต้องการสร้าง Slice ให้เปิดโปรเจ็กต์ Android Studio แล้วคลิกขวาที่ src
แพ็กเกจ แล้วเลือก ใหม่... อื่นๆ > Slice Provider การดำเนินการนี้จะสร้างชั้นเรียน
ที่ขยาย SliceProvider
ให้เพิ่ม
ป้อนข้อมูลผู้ให้บริการที่จำเป็นลงใน AndroidManifest.xml
ของคุณและแก้ไข
build.gradle
เพื่อเพิ่มทรัพยากร Dependency ของ Slice ที่จำเป็น
การแก้ไข 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>
เพิ่มทรัพยากร Dependency ต่อไปนี้ไปยัง build.gradle
แล้ว
Kotlin
dependencies { // ... implementation "androidx.slice:slice-builders-ktx:(latest version)" // ... }
Java
dependencies { // ... implementation "androidx.slice:slice-builders:(latest version)" // ... }
แต่ละส่วนมี URI ที่เชื่อมโยงอยู่ เมื่อพื้นผิวต้องการแสดงสไลซ์
ส่งคำขอการเชื่อมโยงไปยังแอปของคุณด้วย URI นี้ จากนั้นแอปของคุณจะจัดการเรื่องนี้
และสร้าง Slice แบบไดนามิกผ่าน
onBindSlice
จากนั้นพื้นผิวจะแสดงส่วนแบ่งได้ตามความเหมาะสม
ด้านล่างเป็นตัวอย่างของเมธอด onBindSlice
ที่ตรวจหา URI /hello
พาธและแสดงผลส่วน 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(); }
ใช้การกำหนดค่าการเรียกใช้ Slice ซึ่งคุณสร้างไว้ในส่วน Slice Viewer
ข้างต้น การส่งผ่านใน URI ของ Slice (เช่น
slice-content://com.android.example.slicesample/hello
) ของ Hello World
Slice เพื่อดูใน Slice Viewer
สไลซ์แบบอินเทอร์แอกทีฟ
เช่นเดียวกับการแจ้งเตือน คุณสามารถจัดการการคลิกใน Slice ได้โดยแนบ
PendingIntent
ออบเจ็กต์ที่
เมื่อมีการโต้ตอบของผู้ใช้ ตัวอย่างด้านล่างเริ่ม
Activity
ที่รับและจัดการไฟล์เหล่านั้นได้
Intent:
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 ยังรองรับอินพุตประเภทอื่นๆ ด้วย เช่น ปุ่มสลับ ซึ่งมีสถานะใน Intent ที่ส่งไปยังแอป
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); }
จากนั้นผู้รับจะตรวจสอบสถานะที่ได้รับได้ดังนี้
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 ในตอนนี้ รวมจำนวนการออกอากาศที่ได้รับในเนื้อหา ได้แก่
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); }
ในตัวอย่างนี้ ขณะที่จำนวนแสดงอยู่ จำนวนจะไม่อัปเดตเอง คุณสามารถ
แก้ไข Broadcast Receiver ของคุณเพื่อแจ้งระบบว่ามีการเปลี่ยนแปลง
โดยใช้
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); } } }
เทมเพลต
Slices รองรับเทมเพลตที่หลากหลาย สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับตัวเลือกเทมเพลตและ ลักษณะการทำงาน โปรดดูที่เทมเพลต