Twórz własne kafelki Szybkich ustawień dla swojej aplikacji

Szybkie ustawienia to kafelki wyświetlane w panelu Szybkie ustawienia, które reprezentują działania, które użytkownicy mogą kliknąć, aby szybko wykonać powtarzające się zadania. Aplikacja może udostępniać użytkownikom niestandardowy kafelek za pomocą TileService klasy i używać obiektu Tile do śledzenia stanu kafelka. Możesz na przykład utworzyć kafelek, który umożliwia użytkownikom włączanie i wyłączanie usługi VPN udostępnianej przez Twoją aplikację.

Panel Szybkich ustawień z włączonym i wyłączonym kafelkiem VPN
Rysunek 1. Panel Szybkie ustawienia z włączonym i wyłączonym kafelkiem VPN.

Kiedy utworzyć kafelek

Zalecamy tworzenie kafelków dla konkretnych funkcji, do których użytkownicy mają często lub szybko uzyskiwać dostęp (albo jedno i drugie). Najskuteczniejsze kafelki to te, które spełniają oba te warunki, czyli zapewniają szybki dostęp do często wykonywanych działań.

Możesz na przykład utworzyć kafelek aplikacji treningowej, który umożliwi użytkownikom szybkie rozpoczęcie sesji treningowej. Nie zalecamy jednak tworzenia kafelka w tej samej aplikacji, który umożliwiałby użytkownikom przeglądanie całej historii treningów.

Przypadki użycia kafelków aplikacji treningowej
Rysunek 2. Przykłady zalecanych i niezgodnych kafelków aplikacji treningowej.

Aby zwiększyć wykrywalność i łatwość użycia kafelka, zalecamy unikanie tych praktyk:

  • Nie używaj kafelków do uruchamiania aplikacji. Zamiast tego użyj skrótu do aplikacji lub standardowego programu uruchamiającego.

  • Nie używaj kafelków do jednorazowych działań użytkownika. Zamiast tego użyj skrótu do aplikacji lub a powiadomienia.

  • Nie twórz zbyt wielu kafelków. Zalecamy maksymalnie 2 kafelki na aplikację. Zamiast tego użyj skrótu do aplikacji.

  • Nie używaj kafelków, które wyświetlają informacje, ale nie są interaktywne dla użytkowników. Zamiast tego użyj powiadomienia lub widżetu.

Tworzenie kafelka

Aby utworzyć kafelek, musisz najpierw utworzyć odpowiednią ikonę kafelka, a następnie utworzyć i zadeklarować TileService w pliku manifestu aplikacji.

Przykład tworzenia kafelka i zarządzania nim znajdziesz w przykładzie Szybkie ustawienia.

Tworzenie ikony niestandardowej

Musisz podać ikonę niestandardową, która będzie wyświetlana na kafelku w panelu Szybkie ustawienia. (Tę ikonę dodasz podczas deklarowania TileService, co opisujemy w następnej sekcji). Ikona musi być biała, bez przezroczystości, mieć przezroczyste tło, wymiary 24 x 24 dp i postać VectorDrawable.

Przykład obiektu rysowalnego wektorowo
Rysunek 3. Przykład grafiki wektorowej.

Utwórz ikonę, która wizualnie sugeruje przeznaczenie kafelka. Dzięki temu użytkownicy mogą łatwo sprawdzić, czy kafelek spełnia ich potrzeby. Możesz na przykład utworzyć ikonę stopera dla kafelka aplikacji treningowej, która umożliwia użytkownikom rozpoczęcie sesji treningowej.

Tworzenie i deklarowanie TileService

Utwórz usługę dla kafelka, która rozszerza klasę TileService.

Kotlin

class MyQSTileService: TileService() {

  // Called when the user adds your tile.
  override fun onTileAdded() {
    super.onTileAdded()
  }
  // Called when your app can update your tile.
  override fun onStartListening() {
    super.onStartListening()
  }

  // Called when your app can no longer update your tile.
  override fun onStopListening() {
    super.onStopListening()
  }

  // Called when the user taps on your tile in an active or inactive state.
  override fun onClick() {
    super.onClick()
  }
  // Called when the user removes your tile.
  override fun onTileRemoved() {
    super.onTileRemoved()
  }
}

Java

public class MyQSTileService extends TileService {

  // Called when the user adds your tile.
  @Override
  public void onTileAdded() {
    super.onTileAdded();
  }

  // Called when your app can update your tile.
  @Override
  public void onStartListening() {
    super.onStartListening();
  }

  // Called when your app can no longer update your tile.
  @Override
  public void onStopListening() {
    super.onStopListening();
  }

  // Called when the user taps on your tile in an active or inactive state.
  @Override
  public void onClick() {
    super.onClick();
  }

  // Called when the user removes your tile.
  @Override
  public void onTileRemoved() {
    super.onTileRemoved();
  }
}

Zadeklaruj TileService w pliku manifestu aplikacji. Dodaj nazwę i etykietę TileService, ikonę niestandardową utworzoną w poprzedniej sekcji oraz odpowiednie uprawnienie.

 <service
     android:name=".MyQSTileService"
     android:exported="true"
     android:label="@string/my_default_tile_label"  // 18-character limit.
     android:icon="@drawable/my_default_icon_label"
     android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
     <intent-filter>
         <action android:name="android.service.quicksettings.action.QS_TILE" />
     </intent-filter>
 </service>

Zarządzanie TileService

Po utworzeniu i zadeklarowaniu TileService w manifeście aplikacji musisz zarządzać jej stanem.

TileService to powiązana usługa. TileService jest powiązana, gdy zażąda tego Twoja aplikacja lub gdy system musi się z nią komunikować. Typowy cykl życia powiązanej usługi obejmuje te 4 metody wywołania zwrotnego: onCreate(), onBind(), onUnbind() i onDestroy(). Te metody są wywoływane przez system za każdym razem, gdy usługa wchodzi w nową fazę cyklu życia.

Omówienie cyklu życia TileService

Oprócz wywołań zwrotnych, które kontrolują cykl życia powiązanej usługi, musisz zaimplementować inne metody specyficzne dla cyklu życia TileService. Te metody mogą być wywoływane poza onCreate() i onDestroy(), ponieważ metody cyklu życia Service i metody cyklu życia TileService są wywoływane w 2 oddzielnych wątkach asynchronicznych.

Cykl życia TileService obejmuje te metody, które są wywoływane przez system za każdym razem, gdy TileService wchodzi w nową fazę cyklu życia:

  • onTileAdded(): ta metoda jest wywoływana tylko wtedy, gdy użytkownik po raz pierwszy doda Twój kafelek, oraz gdy go usunie i doda ponownie. Jest to najlepszy moment na jednorazową inicjację. Może się jednak okazać, że nie wystarczy to do przeprowadzenia całej inicjacji.

  • onStartListening() i onStopListening(): te metody są wywoływane za każdym razem, gdy aplikacja aktualizuje kafelek, i są wywoływane często. TileService pozostaje powiązana między onStartListening() a onStopListening(), co umożliwia aplikacji modyfikowanie kafelka i przesyłanie aktualizacji.

  • onTileRemoved(): ta metoda jest wywoływana tylko wtedy, gdy użytkownik usunie Twój kafelek.

Wybieranie trybu nasłuchiwania

TileService nasłuchuje w trybie aktywnym lub nieaktywnym. Zalecamy używanie trybu aktywnego, który musisz zadeklarować w manifeście aplikacji. W przeciwnym razie TileService działa w trybie standardowym i nie trzeba jej deklarować.

Nie zakładaj, że TileService będzie działać poza parą metod onStartListening() i onStopListening().

Użyj trybu aktywnego w przypadku TileService, która nasłuchuje i monitoruje swój stan w swoim własnym procesie. TileService w trybie aktywnym jest powiązana z onTileAdded(), onTileRemoved(), zdarzeniami kliknięcia oraz na żądanie procesu aplikacji.

Zalecamy tryb aktywny, jeśli TileService jest powiadamiana, gdy jej własny proces powinien zaktualizować stan kafelka. Aktywne kafelki ograniczają obciążenie systemu, ponieważ nie muszą być powiązane za każdym razem, gdy panel Szybkie ustawienia staje się widoczny dla użytkownika.

Aby zażądać rozpoczęcia nasłuchiwania i otrzymać wywołanie zwrotne do onStartListening(), możesz wywołać statyczną metodę TileService.requestListeningState().

Aby zadeklarować tryb aktywny, dodaj META_DATA_ACTIVE_TILE do pliku manifestu aplikacji.

<service ...>
    <meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
         android:value="true" />
    ...
</service>

Tryb nieaktywny

Tryb nieaktywny to tryb standardowy. TileService jest w trybie nieaktywnym, jeśli jest powiązana za każdym razem, gdy kafelek jest widoczny dla użytkownika. Oznacza to, że TileService może być tworzona i powiązywana ponownie w momentach, na które nie ma wpływu. Może też zostać odłączona i zniszczona, gdy użytkownik nie będzie wyświetlać kafelka.

Po otwarciu przez użytkownika panelu Szybkie ustawienia aplikacja otrzyma wywołanie zwrotne do onStartListening(). Obiekt Tile możesz aktualizować dowolną liczbę razy między onStartListening() a onStopListening().

Nie musisz deklarować trybu nieaktywnego – po prostu nie dodawaj META_DATA_ACTIVE_TILE do pliku manifestu aplikacji.

Omówienie stanów kafelka

Gdy użytkownik doda Twój kafelek, zawsze będzie on w jednym z tych stanów.

  • STATE_ACTIVE: wskazuje stan włączony lub aktywny. W tym stanie użytkownik może wchodzić w interakcję z kafelkiem.

    Na przykład w przypadku kafelka aplikacji treningowej, który umożliwia użytkownikom rozpoczęcie sesji treningowej z odliczaniem czasu, STATE_ACTIVE oznaczałby, że użytkownik rozpoczął sesję treningową i stoper działa.

  • STATE_INACTIVE: wskazuje stan wyłączony lub wstrzymany. W tym stanie użytkownik może wchodzić w interakcję z kafelkiem.

    W przypadku kafelka aplikacji treningowej w stanie STATE_INACTIVE oznaczałoby to, że użytkownik nie rozpoczął sesji treningowej, ale może to zrobić, jeśli chce.

  • STATE_UNAVAILABLE: wskazuje stan tymczasowo niedostępny. W tym stanie użytkownik nie może wchodzić w interakcję z kafelkiem.

    Na przykład kafelek w stanie STATE_UNAVAILABLE oznacza, że z jakiegoś powodu nie jest on obecnie dostępny dla użytkownika.

System ustawia tylko stan początkowy obiektu Tile. Stan obiektu Tile ustawiasz przez resztę jego cyklu życia.

System może przyciemnić ikonę i tło kafelka, aby odzwierciedlić stan obiektu Tile. Obiekty Tile ustawione na STATE_ACTIVE są najciemniejsze, a STATE_INACTIVE i STATE_UNAVAILABLE są coraz jaśniejsze. Dokładny odcień zależy od producenta i wersji.

Kafel VPN jest przyciemniony, aby odzwierciedlać stany obiektów
Rysunek 4. Przykłady kafelka przyciemnionego w celu odzwierciedlenia jego stanu (odpowiednio aktywnego, nieaktywnego i niedostępnego).

Aktualizowanie kafelka

Kafelek możesz zaktualizować po otrzymaniu wywołania zwrotnego do onStartListening(). W zależności od trybu kafelka można go zaktualizować co najmniej raz do momentu otrzymania wywołania zwrotnego do onStopListening().

W trybie aktywnym możesz zaktualizować kafelek dokładnie raz przed otrzymaniem wywołania zwrotnego do onStopListening(). W trybie nieaktywnym możesz aktualizować kafelek dowolną liczbę razy między onStartListening() a onStopListening().

Obiekt Tile możesz pobrać, wywołując getQsTile(). Aby zaktualizować określone pola obiektu Tile, wywołaj te metody:

Gdy skończysz ustawiać pola obiektu Tile na prawidłowe wartości, musisz wywołać updateTile(), aby zaktualizować kafelek. Spowoduje to, że system przeanalizuje zaktualizowane dane kafelka i zaktualizuje interfejs.

Kotlin

data class StateModel(val enabled: Boolean, val label: String, val icon: Icon)

override fun onStartListening() {
  super.onStartListening()
  val state = getStateFromService()
  qsTile.label = state.label
  qsTile.contentDescription = tile.label
  qsTile.state = if (state.enabled) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.icon = state.icon
  qsTile.updateTile()
}

Java

public class StateModel {
  final boolean enabled;
  final String label;
  final Icon icon;

  public StateModel(boolean e, String l, Icon i) {
    enabled = e;
    label = l;
    icon = i;
  }
}

@Override
public void onStartListening() {
  super.onStartListening();
  StateModel state = getStateFromService();
  Tile tile = getQsTile();
  tile.setLabel(state.label);
  tile.setContentDescription(state.label);
  tile.setState(state.enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setIcon(state.icon);
  tile.updateTile();
}

Obsługa kliknięć

Użytkownicy mogą kliknąć Twój kafelek, aby wywołać działanie, jeśli jest on w stanie STATE_ACTIVE lub STATE_INACTIVE. System wywołuje wtedy wywołanie zwrotne onClick() aplikacji.

Gdy aplikacja otrzyma wywołanie zwrotne do onClick(), może uruchomić okno lub aktywność, wywołać działanie w tle lub zmienić stan kafelka.

Kotlin

var clicks = 0
override fun onClick() {
  super.onClick()
  counter++
  qsTile.state = if (counter % 2 == 0) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
  qsTile.label = "Clicked $counter times"
  qsTile.contentDescription = qsTile.label
  qsTile.updateTile()
}

Java

int clicks = 0;

@Override
public void onClick() {
  super.onClick();
  counter++;
  Tile tile = getQsTile();
  tile.setState((counter % 2 == 0) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
  tile.setLabel("Clicked " + counter + " times");
  tile.setContentDescription(tile.getLabel());
  tile.updateTile();
}

Uruchamianie okna

showDialog() zwija panel Szybkie ustawienia i wyświetla okno. Użyj okna, aby dodać kontekst do działania, jeśli wymaga ono dodatkowych danych wejściowych lub zgody użytkownika.

Uruchamianie aktywności

startActivityAndCollapse() uruchamia aktywność, zwijając panel. Aktywności są przydatne, jeśli trzeba wyświetlić więcej szczegółowych informacji niż w oknie lub jeśli działanie jest bardzo interaktywne.

Jeśli aplikacja wymaga znacznej interakcji z użytkownikiem, powinna uruchamiać aktywność tylko w ostateczności. Zamiast tego rozważ użycie okna lub przełącznika.

Długie naciśnięcie kafelka powoduje wyświetlenie ekranu Informacje o aplikacji. Aby zastąpić to zachowanie i zamiast tego uruchomić aktywność ustawiania preferencji, dodaj <intent-filter> do jednej z aktywności z ACTION_QS_TILE_PREFERENCES.

Od Androida API 28 PendingIntent musi mieć Intent.FLAG_ACTIVITY_NEW_TASK:

if (Build.VERSION.SDK_INT >= 28) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}

Możesz też dodać flagę w AndroidManifest.xml w sekcji konkretnej Activity.

Oznaczanie kafelka jako przełączalnego

Zalecamy oznaczanie kafelka jako przełączalnego, jeśli działa on głównie jako przełącznik dwustanowy (co jest najczęstszym zachowaniem kafelków). Pomaga to przekazywać informacje o zachowaniu kafelka do systemu operacyjnego i poprawiać ogólną dostępność.

Aby oznaczyć kafelek jako przełączalny, ustaw metadane TOGGLEABLE_TILE na true.

<service ...>
  <meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
    android:value="true" />
</service>

Wykonywanie tylko bezpiecznych działań na bezpiecznie zablokowanych urządzeniach

Kafelek może być wyświetlany na ekranie blokady zablokowanych urządzeń. Jeśli kafelek zawiera poufne informacje, sprawdź wartość isSecure(), aby określić, czy urządzenie jest w stanie bezpiecznym, a TileService powinna odpowiednio zmienić swoje zachowanie.

Jeśli działanie kafelka jest bezpieczne do wykonania, gdy urządzenie jest zablokowane, użyj startActivity() aby uruchomić aktywność na ekranie blokady.

Jeśli działanie kafelka jest niebezpieczne, użyj unlockAndRun(), aby poprosić użytkownika o odblokowanie urządzenia. Jeśli się to uda, system wykona obiekt Runnable przekazany do tej metody.

Kategoryzowanie kafelka

Aby poprawić komfort użytkowników w Szybkich ustawieniach, możesz skategoryzować kafelek. System porządkuje kafelki w kategorie takie jak Łączność, Wyświetlanie i Prywatność. System używa tych kategorii do sortowania i grupowania kafelków w trybie edycji Szybkich ustawień, co ułatwia użytkownikom znajdowanie i zarządzanie nimi.

Implementacja

Aby określić kategorię dla TileService, dodaj pole metadanych do deklaracji usługi w pliku AndroidManifest.xml:

  • W pliku AndroidManifest.xml w elemencie <service> dla TileService dodaj element <meta-data>.
  • android:name: ustaw tę wartość na android.service.quicksettings.TILE_CATEGORY.
  • android:value: przypisz jedną ze wstępnie zdefiniowanych stałych kategorii, np. android.service.quicksettings.CATEGORY_CONNECTIVITY lub android.service.quicksettings.CATEGORY_DISPLAY.

Jak pokazano w tym przykładzie:

<service
    android:name=".MyConnectivityTileService"
    [...]
    >
    <meta-data android:name="android.service.quicksettings.TILE_CATEGORY"
        android:value="android.service.quicksettings.CATEGORY_CONNECTIVITY" />
</service>

Interfejs API udostępnia zestaw wstępnie zdefiniowanych kategorii do wyboru. Te kategorie są zdefiniowane jako stałe ciągi znaków w klasie TileService.

Jeśli kategoria nie zostanie określona, system automatycznie przypisze kategorię domyślną:

  • Z aplikacji systemowych: w przypadku kafelków, które są częścią aplikacji systemowej.
  • Z zainstalowanych aplikacji: w przypadku kafelków z aplikacji zainstalowanych przez użytkownika.

Chociaż urządzenia Google Pixel korzystają z kategorii w Szybkich ustawieniach, producenci OEM mogą używać tych informacji o kategoriach w swoich interfejsach systemowych lub je ignorować.

Prośba o dodanie kafelka

Aby ręcznie dodać kafelek, użytkownicy muszą wykonać kilka czynności:

  1. Przesuń palcem w dół, aby otworzyć panel Szybkie ustawienia.
  2. Kliknij przycisk edycji.
  3. Przewiń wszystkie kafelki na urządzeniu, aż znajdziesz swój kafelek.
  4. Naciśnij i przytrzymaj kafelek, a następnie przeciągnij go na listę aktywnych kafelków.

Użytkownik może też w dowolnym momencie przenieść lub usunąć Twój kafelek.

Od Androida 13 możesz użyć metody requestAddTileService(), aby znacznie ułatwić użytkownikom dodawanie kafelka do urządzenia. Ta metoda wyświetla użytkownikom prośbę o szybkie dodanie kafelka bezpośrednio do panelu Szybkie ustawienia. Prośba zawiera nazwę aplikacji, podaną etykietę i ikonę.

Prompt interfejsu Quick Settings Placement API
Rysunek 5. Prośba interfejsu API umieszczania w Szybkich ustawieniach.
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

Wywołanie zwrotne zawiera informacje o tym, czy kafelek został dodany, nie został dodany, czy już był, czy wystąpił błąd.

Podczas decydowania, kiedy i jak często wyświetlać prośby, kieruj się własnym uznaniem. Zalecamy wywoływanie requestAddTileService() tylko w kontekście – na przykład wtedy, gdy użytkownik po raz pierwszy wchodzi w interakcję z funkcją, którą ułatwia Twój kafelek.

Jeśli użytkownik wystarczająco często odrzuci prośbę, system może przestać przetwarzać żądania dotyczące danego ComponentName. Użytkownik jest określany na podstawie Context używanego do pobierania tej usługi – musi on odpowiadać bieżącemu użytkownikowi.