توضّح لك هذه الصفحة كيفية إعداد بيئتك وإنشاء الشرائح في تطبيقك:
ملاحظة: يحتوي الإصدار 3.2 من "استوديو Android" أو الإصدارات الأحدث على إضافات أدوات ووظائف يمكن أن تساعدك في تطوير "الشرائح":
- أداة إعادة الهيكلة لنظام AndroidX: مطلوبة إذا كنت تعمل في مشروع يستخدم مكتبات AndroidX.
- تقسيم عمليات فحص الوبر: لرصد الممارسات المضادة الشائعة عند إنشاء شرائح
- نموذج
SliceProvider
: يعالج النص النموذجي عند إنشاءSliceProvider
تنزيل وتثبيت "عارض الشرائح"
تنزيل أحدث عيّنة
إصدار APK لعارض الشرائح
التي يمكنك استخدامها لاختبار الشرائح بدون تنفيذ
SliceView
API.
إذا لم يتم إعداد ADB بشكل صحيح في بيئتك، راجع لمزيد من المعلومات، يمكنك الانتقال إلى دليل Ads Data Hub.
ثبِّت عارض الشرائح على جهازك من خلال تنفيذ الأمر التالي في
الدليل نفسه مثل slice-viewer.apk
الذي تم تنزيله:
adb install -r -t slice-viewer.apk
تشغيل عارض الشرائح
يمكنك تشغيل Slice Viewer إما من مشروعك على "استوديو Android" أو من سطر الأوامر:
تشغيل Slice Viewer من مشروعك على "استوديو Android"
- في مشروعك، اختَر تشغيل > تعديل الإعدادات...
- في أعلى يمين الصفحة، انقر على علامة الجمع الخضراء.
اختَر تطبيق Android.
أدخِل شريحة في حقل الاسم.
اختَر وحدة التطبيق في القائمة المنسدلة الوحدة.
ضمن خيارات الإطلاق، اختَر عنوان URL من القائمة المنسدلة الإطلاق.
يُرجى إدخال
slice-<your slice URI>
في حقل عنوان URL.مثال:
slice-content://com.example.your.sliceuri
انقر على حسنًا.
تشغيل أداة Slice Viewer عبر ADB (سطر الأوامر)
لتشغيل تطبيقك من "استوديو Android":
adb install -t -r <yourapp>.apk
يمكنك عرض شريحتك بتشغيل الأمر التالي:
adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>
عارِض شرائح يعرض شريحة WiFi واحدة
عرض كل الشرائح في مكان واحد
بالإضافة إلى إطلاق شريحة واحدة، يمكنك عرض قائمة دائمة شرائح.
- استخدِم شريط البحث للبحث يدويًا عن الشرائح عبر عنوان URI (على سبيل المثال،
content://com.example.android.app/hello
). في كل مرة تبحث فيها، يتم عرض تمت إضافته إلى القائمة. - عندما تقوم بتشغيل أداة Slice Viewer باستخدام معرف موارد منتظم (URI) الخاص بالشريحة، تتم إضافة الشريحة. إلى القائمة.
- ويمكنك تمرير شريحة لإزالتها من القائمة.
- انقر على معرّف الموارد المنتظم (URI) الخاص بالقطعة لعرض صفحة تحتوي على تلك الشريحة فقط. تحتوي هذه النتيجة على يكون له نفس تأثير تشغيل Slice Viewer باستخدام معرف موارد منتظم (URI) لشرائح.
عارِض الشرائح يعرض قائمة بالشرائح
عرض الشريحة في أوضاع مختلفة
يمكن لأي تطبيق يقدّم شريحة تعديل
SliceView#mode
في وقت التشغيل، لذا يجب التأكد من ظهور الشريحة كما هو متوقع في كل وضع.
حدد رمز القائمة في الجانب العلوي الأيسر من الصفحة لتغيير الوضع.
عارض تقطيع واحد مع ضبط الوضع على "صغير"
إنشاء أول شريحة لك
لإنشاء شريحة، افتح مشروعك على "استوديو Android" وانقر بزر الماوس الأيمن على src
.
الحزمة، وحدد جديد... > غير ذلك > ماكينة التقطيع: يؤدي هذا إلى إنشاء فئة
يمتد إلى SliceProvider
، ويضيف
إدخال مقدم الخدمة المطلوب في AndroidManifest.xml
وتعديل
build.gradle
لإضافة تبعيات الشرائح المطلوبة.
يظهر أدناه التعديل الذي تم إجراؤه على 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>
تمت إضافة الموارد التابعة التالية إلى build.gradle
:
Kotlin
dependencies { // ... implementation "androidx.slice:slice-builders-ktx:(latest version)" // ... }
Java
dependencies { // ... implementation "androidx.slice:slice-builders:(latest version)" // ... }
ولكل شريحة معرّف موارد منتظم (URI) مرتبط بها. عندما يريد أحد الأسطح عرض شريحة،
يرسل طلب الربط إلى تطبيقك باستخدام معرّف الموارد المنتظم (URI) هذا. يعالج تطبيقك بعد ذلك هذا الإجراء.
وإنشاء الشريحة ديناميكيًا عبر
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(); }
استخدِم إعداد تشغيل الشريحة الذي أنشأته في قسم "عارض الشرائح".
أعلاه، إدخال عنوان URI في Slice (على سبيل المثال،
slice-content://com.android.example.slicesample/hello
) من Hello World
التقطيع لعرضه في عارض الشرائح.
شرائح تفاعلية
كما هي الحال مع الإشعارات، يمكنك التعامل مع النقرات داخل الشريحة من خلال إرفاق
PendingIntent
من الكائنات
تحدث عند تفاعل المستخدم. يبدأ المثال أدناه
Activity
الذي يمكنه تلقّي هذه الطلبات ومعالجتها
الأهداف:
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" ); }
تتوافق الشرائح أيضًا مع أنواع مصادر الإدخال الأخرى، مثل مفاتيح التبديل التي تتضمّن الحالة في الغرض الذي يتم إرساله إلى التطبيق.
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(); } } }
شرائح ديناميكية
يمكن أن تتضمّن الشرائح أيضًا محتوى ديناميكيًا. في المثال التالي، الشريحة الآن يشمل عدد عمليات البث المستلمة في محتواه:
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); }
في هذا المثال، بينما يظهر العدد، لا يتم تعديله من تلقاء نفسه. يمكنك
تعديل جهاز استقبال البث لإعلام النظام بحدوث تغيير
باستخدام
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); } } }
النماذج
تتيح الشرائح استخدام مجموعة متنوعة من النماذج. لمزيد من التفاصيل حول خيارات النماذج وسلوكيات المستخدمين، يُرجى مراجعة النماذج.