Własne kafelki szybkich ustawień w Android 7

Własne kafelki szybkich ustawień w Android 7
W ostatnich wydaniach systemu Android ustawienia przeszły małą rewolucję. Przeorganizowany został główny ekran ustawień, dodano nowe opcje. Android Lollipop wprowadził skróty do szybkiego przełączania najistotniejszych ustawień tak, aby były one widoczne bezpośrednio po rozwinięciu górnego panelu. Android Nougat, wraz z API 24, udostępnił nam możliwość dodawania tam własnych ustawień, związanych z naszą aplikacją.

Kiedy warto dodawać swoje ustawienia?

Nie powinniśmy nadużywać tej możliwości. Nie może to być dodatkowy skrót do normalnego włączania naszej aplikacji. Od tego mamy pulpit. Motywacją do stworzenia własnego kafelka powinna być chęć udostępnienia szybkiej możliwości zmiany jakiegoś ustawienia lub włączenia aplikacji w konkretnym trybie. Niezbędnym warunkiem jest to, aby powiązana akcja była dla użytkownika wystarczająco pilna i przynajmniej teoretycznie często używana. Nie może być to zmiana jakiejś podrzędnej opcji. Nie powinna być to też akcja, którą standardowy, aktywny użytkownik naszej aplikacji użyje 2-3 razy do roku. Wtedy naprawdę nie ma to sensu.

Quick tiles panel in Android

Dobrą praktyką może być pokazanie dialogu z zapytaniem, czy użytkownik na pewno chce wykonać daną akcję, szczególnie jeśli jest nieodwracalna lub długotrwała.

Przykłady dobrego użycia

  • Zdalne uruchomienie zewnętrznego urządzenia lub zmiana trybu (zgaszenie światła w inteligentnym domu, monitoring, uruchomienie sprzątającego robota).
  • Włączenie/wyłączenie pracy w tle naszej aplikacji, synchronizacja danych.
  • Otwarcie aplikacji na konkretnym, ważnym ekranie aplikacji najlepiej z dodatkowymi opcjami.

Jak to zrobić?

Całą kontrolę nad kafelkiem implementujemy w dedykowanym mu własnym serwisie rozszerzając klasę TileService. Klasa dostępna jest od API 24, a nasza aplikacja prawdopodobnie ma zamiar wspierać też niższe systemy. Nie ma ku temu przeszkód. Wtedy ta opcja po prostu nie będzie dostępna dla użytkownika. Wystarczy oznaczyć nasz serwis odpowiednią adnotacją:

@TargetApi(Build.VERSION_CODES.N)

Jak w przypadku każdego serwisu musimy też zdefiniować go w manifeście. Szczególną uwagę zwróćmy na nazwę pozwolenia oraz akcję, na którą nasłuchujemy.

W samej implementacji klasy będziemy mogli nadpisać następujące metody:

  • onTileAdded() – wywoływana, kiedy użytkownik doda nasz kafelek do własnego panelu (tu należy zaznaczyć, że aplikacja może dodać kafelek do zbioru dostępnych, natomiast użytkownik sam musi edytować górny panel i przeciągnąć go do aktywnie używanych kafelków)
  • onStartListening() – wywoływana, kiedy kafelek staje się widoczny np po wysunięciu górnego panelu
  • onClick() – wywoływana, kiedy użytkownik kliknie kafelek
  • onStopListening() – wywoływana, kiedy kafelek przestaje być widoczny na ekranie
  • onTileRemoved() – wywoływana, kiedy kafelek zostaje usunięty z aktualnie używanych w panelu

Podpięcie się pod powyższe metody da nam pełną kontrolę nad tym co się dzieje i pozwoli odpowiednio zareagować oraz ewentualnie zmienić stan widoku samego kafelka. Może on być niezmienialny, kiedy mamy do czynienia z pojedynczą akcją, natomiast przeważnie powinien odzwierciedlać aktywny lub nieaktywny stan wybranej opcji. Można również ustawić stan niedostępny, wtedy kafelek będzie wyszarzony i nieklikalny. Przydatne w momencie, kiedy dane urządzenie nie wspiera naszej funkcjonalności i dajmy na to nie posiada modułu bluetooth w odpowiedniej wersji lub nie mamy połączenia z internetem. Przykładowa implementacja metody reagującej na kliknięcie i zmieniającej stan kafelka:

/**
* Called when the user taps the tile.
*/
@Override
public void onClick() {
   Log.d("QS", "Tile tapped");
   //do your stuff here
   updateTile();
}


// Changes the appearance of the tile.
private void updateTile() {
   Tile tile = this.getQsTile();
   boolean isActive = getServiceStatus();


   Icon newIcon = Icon.createWithResource(getApplicationContext(),
          isActive ? android.R.drawable.ic_lock_power_off : ic_android_black_24dp);
   StringBuilder stringBuilder = new StringBuilder();
   stringBuilder
           .append(getString(R.string.tile_label))
           .append(" ")
           .append(getString(isActive ? R.string.service_inactive : R.string.service_active));
   String newLabel = stringBuilder.toString();
   int newState = isActive ? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE;


   // Change the UI of the tile.
   tile.setLabel(newLabel);
   tile.setIcon(newIcon);
   tile.setState(newState);


   // Need to call updateTile for the tile to pick up changes.
   tile.updateTile();
}

Bezpieczeństwo

Bardzo ważne jest, żeby pamiętać o możliwości wysunięcia panelu górnego przez użytkownika, kiedy ekran jest zablokowany. Nie możemy wtedy udostępniać żadnych newralgicznych opcji ani akcji. Inaczej całe zabezpieczenie telefonu pinem, wzorem do narysowania czy nawet odciskiem palca może pójść na marne. Jeśli uznamy, że dana opcja nie powinna być możliwa do uruchomienia na ekranie blokady istnieje proste rozwiązanie. Klasa TileService, którą rozszerzamy, daje nam metodę:

void unlockAndRun(Runnable runnable);

Dzięki niej możemy wywołać prośbę o odblokowanie telefonu i dopiero wtedy natychmiast wywołać naszą akcję. To czy telefon jest zablokowany powie nam metoda isLocked(). Jeśli chcemy wywołać akcję na zablokowanym ekranie i naprawdę nie potrzebujemy autoryzacji musimy pamiętać, że niemożliwe będzie pokazanie dialogu. Możemy natomiast uruchomić własną aktywność, która ustawia flagę FLAG_SHOW_WHEN_LOCKED na getWindow() w Aktywności. Do uruchomienia najlepiej użyć metody startActivityAndCollapse, aby schować automatycznie górny panel i użytkownik zauważył, że w ogóle coś się stało.

Zachęcam do korzystania z możliwości dodawania własnych kafelków. Róbmy to jednak z umiarem, a nie na siłę. Panel powinien mieć tylko najpilniejsze i najczęściej używane skróty, więc postarajmy się nie zrobić z niego śmietniska ikonek 🙂 Chyba żaden użytkownik by tego nie chciał.

Dowiedz się więcej

Android Small Talks: Wstrzykiwanie zależności poprzez Daggera 2

Wstrzykiwanie zależności jest wzorcem projektowym, którego głównym zadaniem jest uwolnienie naszego kodu od zależności. Jak wszyscy na pewno zdajemy sobie sprawę, kod, który ma minimalną ilość zależności jest zdecydowanie łatwiejszy do zarządzania oraz zmiany. Łatwiej jest też taki kod wykorzystać i przetestować.
Przeczytaj

ConstraintLayout, czyli jednak nie tak prędko…

Przeglądając ostatnimi czasy nowinki ze świata Androida trafiłam na pojęcie ConstraintLayout. Jest to nowy dostarczony przez Androida i Google layout, wspierający wersje Androida aż od API 9. Wczytując się w możliwości, jakie ma dawać, stwierdziłam, że sprawdzę, jak zachowuje się nowy Layout Builder i jak wygląda posługiwanie się ConstraintLayoutem.
Przeczytaj

Tworzenie BuildVariants poprzez Gradle krok po kroku

Podczas tworzenia aplikacji nieraz zdarza się, że w pewnym momencie chcemy uzyskać kilka wersji naszej aplikacji, które różnią się mniej lub bardziej istotnymi detalami. Aby w łatwy sposób stworzyć różne wersje aplikacji, wystarczy dokonać kilku zmian w Gradle.
Przeczytaj

Wycena projektu

Sprawdź, jak wykorzystujemy naszą wiedzę w praktyce i stwórz z nami swój projekt.

Dlaczego warto rozwijać z nami projekty?

Logo Mobile Trends Awards

Mobile Trends Awards 2017

Nominacja w kategorii M-COMMERCE

17

opinii klientów

Clutch logo
Logo Legalni bukmacherzy

Nagroda Legalnych Bukmacherów 2019

Najlepsza aplikacja mobilna

60+

zrealizowanych projektów