Na tej stronie dowiesz się, jak skonfigurować środowisko i kompilować Wycinki w aplikacji.
Uwaga: Android Studio 3.2 lub nowsza wersja zawiera dodatkowe narzędzia i funkcje, które ułatwiają tworzenie wycinków:
- Narzędzie do refaktoryzacji AndroidaX: wymagane, jeśli pracujesz w projekcie, korzysta z bibliotek AndroidaX.
- Wycinanie lint: wykrywa powszechne blokady zapobiegające praktykom podczas budowania Wycinki
- Szablon
SliceProvider
: obsługuje schemat, gdy TworzęSliceProvider
Pobieranie i instalowanie przeglądarki wycinków
Pobierz najnowszy fragment
Wersja pakietu APK przeglądarki wycinków
którego można używać do testowania wycinków bez implementowania
Interfejs API SliceView
.
Jeśli usługa ADB nie jest poprawnie skonfigurowana w Twoim środowisku, zapoznaj się z Przeczytaj przewodnik na temat ADB.
Zainstaluj przeglądarkę wycinków na urządzeniu, uruchamiając następujące polecenie w
w tym samym katalogu co pobrany plik slice-viewer.apk
:
adb install -r -t slice-viewer.apk
Uruchamianie przeglądarki wycinków
Podgląd wycinków możesz uruchomić z projektu Android Studio lub wiersz poleceń:
Uruchamianie przeglądarki wycinków z poziomu projektu Android Studio
- W projekcie wybierz Uruchom > Edytuj konfiguracje...
- W lewym górnym rogu kliknij zielony znak plus.
Wybierz Aplikacja na Androida.
W polu nazwy wpisz wycinek.
W menu Moduł wybierz moduł aplikacji.
W sekcji Opcje uruchamiania wybierz Adres URL z menu Uruchom.
Wpisz
slice-<your slice URI>
w polu adresu URLPrzykład:
slice-content://com.example.your.sliceuri
Kliknij OK.
Uruchom przeglądarkę wycinków za pomocą ADB (wiersza poleceń)
Uruchamianie aplikacji z Android Studio:
adb install -t -r <yourapp>.apk
Wyświetl wycinek, uruchamiając następujące polecenie:
adb shell am start -a android.intent.action.VIEW -d slice-<your slice URI>
Przeglądarka wycinka z jednym wycinkiem Wi-Fi
Wyświetl wszystkie wycinki w jednym miejscu
Oprócz uruchomienia pojedynczego wycinka możesz wyświetlić stałą listę swoich Wycinki.
- Użyj paska wyszukiwania, aby ręcznie wyszukać wycinki według identyfikatora URI (na przykład
content://com.example.android.app/hello
). Przy każdym wyszukiwaniu wycinek jest dodano do listy. - Za każdym razem, gdy uruchamiasz narzędzie Podgląd wycinka z identyfikatorem URI wycinka, wycinek jest dodawany z listy.
- Wycinek możesz usunąć z listy, przesuwając.
- Dotknij identyfikatora URI wycinka, aby wyświetlić stronę zawierającą tylko ten wycinek. Zawiera taki sam efekt jak uruchomienie przeglądarki wycinka z identyfikatorem URI wycinka.
Przeglądarka wycinków z listą wycinków
Wyświetlanie wycinka w różnych trybach
Aplikacja wyświetlająca wycinek może modyfikować
SliceView#mode
w czasie działania, więc upewnij się, że wycinek wygląda zgodnie z oczekiwaniami w każdym trybie.
Aby zmienić tryb, kliknij ikonę menu w prawym górnym rogu strony.
Przeglądarka z jednym wycinkiem z trybem „mały”
Utwórz pierwszy wycinek
Aby utworzyć wycinek, otwórz projekt Android Studio, kliknij prawym przyciskiem myszy src
pakietu i wybierz Nowy... > Inne > Dostawca wycinka. Spowoduje to utworzenie klasy
która rozciąga się na SliceProvider
, dodaje
wymagany wpis dostawcy na koncie AndroidManifest.xml
, modyfikując
build.gradle
, aby dodać wymagane zależności wycinka.
Zmiana w działaniu AndroidManifest.xml
jest widoczna poniżej:
<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>
Do elementu build.gradle
zostaną dodane te zależności:
Kotlin
dependencies { // ... implementation "androidx.slice:slice-builders-ktx:(latest version)" // ... }
Java
dependencies { // ... implementation "androidx.slice:slice-builders:(latest version)" // ... }
Każdy wycinek ma powiązany identyfikator URI. Gdy powierzchnia chce wyświetlić wycinek,
wysyła do aplikacji żądanie powiązania z tym identyfikatorem URI. Aplikacja obsługuje te procesy
i dynamicznie tworzy wycinek za pomocą
onBindSlice
. Na powierzchni może wtedy w razie potrzeby wyświetlić wycinek.
Poniżej znajdziesz przykład metody onBindSlice
, która sprawdza identyfikator URI /hello
i zwraca wycinek 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(); }
Użyj konfiguracji uruchomienia wycinka utworzonej w sekcji Wyświetlający wycinki
powyżej, podając identyfikator URI wycinka (na przykład
slice-content://com.android.example.slicesample/hello
) z Hello World
Wycinek, aby wyświetlić go w przeglądarce wycinków.
Wycinki interaktywne
Podobnie jak w przypadku powiadomień, możesz obsługiwać kliknięcia na swoim wycinku, dołączając
PendingIntent
obiektów, które są
uruchamianych w wyniku interakcji użytkownika. Poniższy przykład zaczyna się
Activity
, które mogą je odbierać i przetwarzać.
intencje:
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" ); }
Wycinki obsługują też inne typy danych wejściowych, takie jak przełączniki, które zawierają stan intencję, która jest wysyłana do aplikacji.
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); }
Odbiorca może sprawdzić swój stan:
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(); } } }
Wycinki dynamiczne
Wycinki mogą też zawierać treści dynamiczne. W poniższym przykładzie funkcja Wycinki obejmuje liczbę transmisji otrzymanych w jej treści:
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); }
W tym przykładzie liczba jest widoczna, ale nie jest aktualizowana automatycznie. Dostępne opcje
zmodyfikować odbiornik w celu powiadomienia systemu o zmianie
za pomocą funkcji
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); } } }
Szablony
Wycinki obsługują różne szablony. Więcej informacji o opcjach szablonów zachowania można znaleźć w sekcji Szablony.