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

Szybkie ustawienia to kafelki wyświetlane na panelu Szybkie ustawienia, które odpowiadają czynnościom, których kliknięcie pozwala użytkownikom szybko wykonywać zadania cykliczne. Aplikacja może udostępniać użytkownikom niestandardowy kafelek w ramach klasy TileService oraz używać obiektu Tile do śledzenia stanu kafelka. Możesz na przykład utworzyć kafelek umożliwiający użytkownikom włączanie i wyłączanie sieci VPN udostępnianej przez Twoją aplikację.

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

Decydowanie, kiedy utworzyć kafelek

Zalecamy tworzenie kafelków dla określonych funkcji, do których użytkownicy powinni często uzyskiwać dostęp lub do których potrzebują szybkiego dostępu (lub obu tych funkcji). Najskuteczniejsze kafelki to te, które pasują do obu tych cech, co zapewnia szybki dostęp do często wykonywanych działań.

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

Przypadki użycia kafelków aplikacji Fitness
Rysunek 2. Przykłady zalecanych i niezalecanych kafelków aplikacji do fitnessu.

Aby poprawić wykrywalność kafelków i ułatwić korzystanie z nich, zalecamy unikanie niektórych metod:

  • Unikaj używania kafelków do uruchamiania aplikacji. Użyj skrótu do aplikacji lub standardowego programu uruchamiającego.

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

  • Unikaj tworzenia zbyt wielu kafelków. Zalecamy używanie maksymalnie dwóch skrótów na aplikację. Zamiast tego użyj skrótu do aplikacji.

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

Utwórz kafelek

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

Przykładowe ustawienia pokazują, jak utworzyć kafelek i nim zarządzać.

Utwórz ikonę niestandardową

Musisz podać niestandardową ikonę, która będzie się wyświetlać na kafelku w panelu Szybkie ustawienia. Dodasz tę ikonę podczas deklarowania TileService zgodnie z opisem w następnej sekcji. Ikona musi być białą, białą i przezroczystym tłem, o wymiarach 24 x 24 dp i mieć postać VectorDrawable.

Przykład elementu rysowalnego wektorowego
Rysunek 3. Przykład elementu rysowalnego w formacie wektorowym.

Utwórz ikonę, która będzie wizualną wskazówką dotyczącą przeznaczenia kafelka. Dzięki temu użytkownicy będą mogli łatwo określić, czy kafelek odpowiada ich potrzebom. Na przykład możesz utworzyć ikonę stopera dla kafelka aplikacji do fitnessu, która umożliwia rozpoczęcie sesji treningowej.

Tworzenie i deklarowanie usługi TileService

Utwórz dla swojego kafelka usługę, 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ę elementu TileService, ikonę niestandardową utworzoną w poprzedniej sekcji oraz odpowiednie uprawnienia.

 <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 usługą TileService

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

TileService jest usługą wiążącą. Zasób TileService jest powiązany, gdy zażąda tego aplikacja lub jeśli system będzie musiał się z nią skomunikować. Typowy cykl życia ograniczonej usługi obejmuje 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 usługi TileService

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

Cykl życia TileService zawiera poniższe metody, które są wywoływane przez system za każdym razem, gdy TileService rozpoczyna nowy etap cyklu życia:

  • onTileAdded(): ta metoda jest wywoływana tylko wtedy, gdy użytkownik doda Twój kafelek po raz pierwszy oraz gdy usunie go i doda ponownie. To najlepszy moment na przeprowadzenie jednorazowej inicjalizacji. Może to jednak nie wystarczyć do zainicjowania wszystkich wymaganych działań.

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

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

Wybierz tryb słuchania

TileService słucha w trybie aktywnym lub nieaktywnym. Zalecamy korzystanie z trybu aktywnego, który musisz zadeklarować w manifeście aplikacji. W przeciwnym razie TileService jest trybem standardowym i nie trzeba go deklarować.

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

Użyj trybu aktywnego dla TileService, który nasłuchuje i monitoruje jego stan we własnym procesie. Element TileService w trybie aktywnym jest powiązany z onTileAdded() i onTileRemoved() zdarzeniami kliknięcia oraz gdy zażąda tego proces aplikacji.

Zalecamy tryb aktywny, jeśli urządzenie TileService otrzymuje powiadomienie o konieczności aktualizacji stanu kafelka przez własny proces. Aktywne kafelki ograniczają obciążenie systemu, ponieważ nie trzeba ich wiązać za każdym razem, gdy panel Szybkich ustawień staje się widoczny dla użytkownika.

Metodę statyczną TileService.requestListeningState() można wywołać, aby zażądać rozpoczęcia stanu nasłuchiwania i otrzymać wywołanie zwrotne onStartListening().

Tryb aktywny możesz zadeklarować, dodając 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. Kafelek TileService jest w trybie nieaktywnym, jeśli jest powiązany za każdym razem, gdy kafelek jest widoczny dla użytkownika. Oznacza to, że usługa TileService może zostać utworzona i powiązana ponownie w niektórych przypadkach poza jej kontrolą. Powiązanie może też zostać usunięte, gdy użytkownik nie wyświetla kafelka.

Gdy użytkownik otworzy panel Szybkie ustawienia, Twoja aplikacja otrzyma wywołanie zwrotne do onStartListening(). Obiekt Tile możesz aktualizować dowolną liczbę razy w okresie od onStartListening() do onStopListening().

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

Omówienie stanów kafelków

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

  • STATE_ACTIVE: wskazuje stan włączenia lub wyłączenia. W tym stanie użytkownik może wchodzić w interakcje z Twoim kafelkiem.

    Na przykład w przypadku kafelka aplikacji do fitnessu, który umożliwia użytkownikom rozpoczęcie sesji treningowej o określonym czasie, STATE_ACTIVE oznacza, że użytkownik rozpoczął sesję treningową, a minutnik jest uruchomiony.

  • STATE_INACTIVE: wskazuje stan wyłączenia lub wstrzymania. W tym stanie użytkownik może wchodzić w interakcje z Twoim kafelkiem.

    Żeby ponownie skorzystać z przykładu kafelka z aplikacją do fitnessu, kafelek w regionie STATE_INACTIVE będzie oznaczać, że użytkownik nie rozpoczął sesji treningowej, ale mógłby to zrobić.

  • STATE_UNAVAILABLE: oznacza stan tymczasowo niedostępny. W tym stanie użytkownik nie może korzystać z Twojego kafelka.

    Na przykład kafelek w regionie STATE_UNAVAILABLE oznacza, że z jakiegoś powodu użytkownik nie jest obecnie dostępny.

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

System może zabarwić ikonę kafelka i tło, aby odzwierciedlić stan obiektu Tile. Obiekty (Tile) z ustawieniem STATE_ACTIVE są najciemniejsze, a obiekty STATE_INACTIVE i STATE_UNAVAILABLE stają się coraz jaśniejsze. Dokładny odcień zależy od producenta i wersji.

Kafelek VPN w kolorze odzwierciedlającym stany obiektu
Rysunek 4. Przykłady kafelka w kolorze odzwierciedlającym stan kafelka (odpowiednio aktywny, nieaktywny i niedostępny).

Zaktualizuj kafelek

Możesz zaktualizować swój kafelek, gdy oddzwonimy do Ciebie (onStartListening()). W zależności od trybu kafelka Twój kafelek można zaktualizować co najmniej raz, dopóki nie odbierzesz wywołania zwrotnego do onStopListening().

W trybie aktywnym możesz zaktualizować kafelek dokładnie raz, zanim otrzymasz wywołanie zwrotne do onStopListening(). W trybie nieaktywnym kafelek możesz aktualizować dowolną liczbę razy w okresie od onStartListening() do onStopListening().

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

Musisz wywołać updateTile(), aby zaktualizować kafelek po ustawieniu prawidłowych wartości w polach obiektu Tile. System przeanalizuje zaktualizowane dane kafelków 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ą klikać Twój kafelek, aby uruchamiać działanie, jeśli znajduje się on w regionie STATE_ACTIVE lub STATE_INACTIVE. Następnie system wywoła wywołanie zwrotne onClick() aplikacji.

Gdy aplikacja otrzyma wywołanie zwrotne do onClick(), może uruchomić okno lub aktywność, rozpocząć pracę w tle albo 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();
}

Otwórz okno

showDialog() zwija panel Szybkie ustawienia i wyświetla okno. Dodaj kontekst do działania za pomocą okna, jeśli wymagane jest dodatkowe dane wejściowe lub zgodę użytkownika.

Uruchamianie aktywności

startActivityAndCollapse() rozpoczyna działanie podczas zwijania panelu. Działania są przydatne, jeśli chcesz wyświetlić bardziej szczegółowe informacje niż w oknie lub jeśli działanie jest wysoce interaktywne.

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

Kliknięcie i przytrzymanie kafelka powoduje wyświetlenie ekranu Informacje o aplikacji dla użytkownika. Aby zastąpić to działanie i w zamian uruchomić działanie związane z określaniem ustawień, dodaj <intent-filter> do jednej ze swoich aktywności za pomocą polecenia ACTION_QS_TILE_PREFERENCES.

Oznacz kafelek jako dostępny do przełączania

Zalecamy oznaczanie kafelka jako możliwego do przełączania, jeśli działa głównie jako przełącznik dwustanowy (jest to typowy sposób działania kafelków). Pomaga to dostarczać informacji o działaniu kafelka z systemem operacyjnym i poprawiać ogólną dostępność.

Ustaw metadane TOGGLEABLE_TILE na true, aby oznaczyć kafelek jako możliwe do przełączania.

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

Wykonuj bezpieczne czynności tylko na bezpiecznie zablokowanych urządzeniach

Twój kafelek może być widoczny u góry ekranu blokady na zablokowanych urządzeniach. Jeśli kafelek zawiera informacje poufne, sprawdź wartość isSecure(), aby określić, czy urządzenie jest w stanie bezpiecznym, a TileService powinien odpowiednio zmienić swoje działanie.

Jeśli działanie kafelka można bezpiecznie wykonać przy zablokowanym ekranie, uruchom aktywność u góry ekranu blokady za pomocą startActivity().

Jeśli działanie związane z kafelkiem jest niebezpieczne, użyj unlockAndRun(), aby poprosić użytkownika o odblokowanie urządzenia. Jeśli operacja się uda, system uruchomi obiekt Runnable przekazany do tej metody.

Poproś użytkownika 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 dziecka, aż go znajdzie.
  4. Przytrzymaj kafelek i przeciągnij go na listę aktywnych kafelków.

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

Począwszy od Androida 13, możesz używać metody requestAddTileService(), aby znacznie ułatwić użytkownikom dodawanie kafelka na urządzeniu. Ta metoda powiadamia użytkowników o prośbie o szybkie dodanie kafelka bezpośrednio do panelu Szybkich ustawień. Prompt zawiera nazwę aplikacji, podaną etykietę i ikonę.

Komunikat interfejsu Quick Settings Placement API
Rysunek 5. Quick Settings Placement API.
public void requestAddTileService (
  ComponentName tileServiceComponentName,
  CharSequence tileLabel,
  Icon icon,
  Executor resultExecutor,
  Consumer<Integer> resultCallback
)

Zawiera ono informacje o tym, czy kafelek został dodany, czy nie został dodany, czy był już obecny i czy wystąpił jakiś błąd.

Decydując, kiedy i jak często użytkownicy będą prosić użytkowników o zgodę, zachowaj ostrożność. Zalecamy wywoływanie funkcji requestAddTileService() tylko w kontekście, na przykład gdy użytkownik po raz pierwszy wejdzie w interakcję z funkcją, którą obsługuje Twój kafelek.

System może zatrzymać przetwarzanie żądań dotyczących określonego typu ComponentName, jeśli użytkownik wcześniej je odrzucił. Użytkownik jest określany na podstawie identyfikatora Context używanego do pobierania tej usługi – musi pasować do bieżącego użytkownika.