Utwórz niestandardowy rodzaj konta

Mówiliśmy już o uzyskiwaniu dostępu do interfejsów API Google, które korzystają z kont i użytkowników zdefiniowanych przez Google. Jeśli jednak masz własną usługę online, nie ma ona kont ani użytkowników Google. Co trzeba zrobić? Okazało się, że instalowanie nowych rodzajów kont na urządzeniu użytkownika jest stosunkowo proste. Z tej lekcji dowiesz się, jak utworzyć konto niestandardowe, które działa tak samo jak konta wbudowane.

Implementacja niestandardowego kodu konta

W pierwszej kolejności musisz mieć możliwość uzyskania danych logowania od użytkownika. Może to być proste okno dialogowe z prośbą o podanie nazwy i hasła. Może to też być bardziej egzotyczna procedura, np. podanie hasła jednorazowego lub skanowanie biometryczne. Tak czy inaczej, Twoim obowiązkiem jest wdrożenie kodu, który:

  1. Zbiera dane logowania od użytkownika
  2. Uwierzytelnia dane logowania na serwerze
  3. Przechowuje dane logowania na urządzeniu

Zwykle wszystkie 3 z tych wymagań można spełnić w ramach jednego działania. Nazywamy to działaniem uwierzytelniania.

Muszą one korzystać z systemu AccountManager, dlatego działania uwierzytelniania mają pewne wymagania, których nie ma normalne. Dla ułatwienia Android Framework udostępnia klasę podstawową, AccountAuthenticatorActivity, którą możesz rozszerzyć, aby utworzyć własny mechanizm uwierzytelniania.

To, w jaki sposób spełnisz 2 pierwsze wymagania związane z aktywnością uwierzytelniającą, czyli zbieraniem danych logowania i uwierzytelnianiem, zależy wyłącznie od Ciebie. (Gdyby istniał tylko jeden sposób, w końcu nie trzeba tworzyć kont niestandardowych). Trzeci wymóg ma kanoniczną, a zarazem prostą implementację:

Kotlin

Account(username, your_account_type).also { account ->
    accountManager.addAccountExplicitly(account, password, null)
}

Java

final Account account = new Account(username, your_account_type);
accountManager.addAccountExplicitly(account, password, null);

Ostrożnie podchodź do kwestii bezpieczeństwa.

Pamiętaj, że AccountManager nie jest usługą szyfrowania ani pękiem kluczy. Dane logowania do konta są przechowywane w takiej postaci, w jakiej je przekazujesz, w formie zwykłych plików tekstowych. W przypadku większości urządzeń stanowi to problem, ponieważ dane są przechowywane w bazie danych, do której dostęp ma tylko użytkownik root. Jednak w przypadku urządzenia z dostępem do roota dane logowania będą widoczne dla każdego, kto ma do niego dostęp adb.

Mając to na uwadze, nie przekazuj rzeczywistego hasła użytkownika firmie AccountManager.addAccountExplicitly(). Zamiast tego lepiej jest przechowywać kryptograficznie bezpieczny token, którego atakujący może użyć w ograniczonym zakresie. Jeśli Twoje dane logowania chronią coś wartościowego, zastanów się, czy nie zrobić tego samego.

Pamiętaj: w przypadku kodu zabezpieczającego przestrzegaj zasady „Pogromcy mitów”: nie próbuj tego w domu. Przed zaimplementowaniem niestandardowego kodu konta skonsultuj się ze specjalistą ds. zabezpieczeń.

Skoro już zniknął wyłączenia odpowiedzialności, czas zająć się refleksją. Masz już zaimplementowany kod niestandardowego konta. Została tylko kanalizacja.

Rozszerz usługę uwierzytelniania konta abstrakcyjnego

Aby AccountManager działał z niestandardowym kodem konta, potrzebujesz klasy implementującej interfejsy, których oczekuje AccountManager. Jest to klasa authenticator.

Najprostszym sposobem utworzenia klasy uwierzytelniającej jest rozszerzenie AbstractAccountAuthenticator i zaimplementowanie jej metod abstrakcyjnych. Jeśli masz już za sobą opanowanie poprzednich lekcji, abstrakcyjne metody w AbstractAccountAuthenticator powinny wyglądać znajomo: są one przeciwieństwem metod uzyskiwania informacji o koncie i tokenów autoryzacji, które były wywoływane przez Ciebie w poprzedniej lekcji.

Prawidłowe zaimplementowanie klasy uwierzytelniającej wymaga kilku osobnych fragmentów kodu. Po pierwsze, AbstractAccountAuthenticator ma 7 metod abstrakcyjnych, które należy zastąpić. Następnie musisz dodać do pliku manifestu aplikacji filtr intencji dla elementu "android.accounts.AccountAuthenticator" (jak pokazano w następnej sekcji). Na koniec musisz podać 2 zasoby XML, które określają (między innymi nazwę niestandardowego typu konta) i ikonę, która będzie wyświetlana przez system obok kont tego typu.

Szczegółowy przewodnik z implementacją skutecznej klasy uwierzytelniania oraz pliki XML znajdziesz w dokumentacji AbstractAccountAuthenticator.

Jeśli aktywność uwierzytelniająca wymaga specjalnych parametrów inicjowania, możesz je dołączyć do intencji za pomocą parametru Intent.putExtra().

Utwórz usługę uwierzytelniającą

Po utworzeniu klasy uwierzytelniania musisz określić miejsce, w którym będzie ona mieszkała. Aplikacje uwierzytelniające konta muszą być dostępne dla wielu aplikacji i działać w tle, dlatego naturalnie muszą działać w obrębie typu Service. Nazywamy ją usługą uwierzytelniającą.

Usługa uwierzytelniająca może być bardzo prosta. Wystarczy, że utworzysz instancję klasy uwierzytelniania w onCreate() i wywołasz metodę getIBinder() w usłudze onBind().

Nie zapomnij dodać tagu <service> do pliku manifestu oraz dodać filtr intencji dla intencji AccountAuthenticator oraz zadeklaruj weryfikatora konta:

<service ...>
   <intent-filter>
      <action android:name="android.accounts.AccountAuthenticator" />
   </intent-filter>
   <meta-data android:name="android.accounts.AccountAuthenticator"
             android:resource="@xml/authenticator" />
</service>

Dystrybucja usługi

Gotowe! System rozpoznaje teraz typ konta, niezależnie od wszelkich znanych typów kont, takich jak „Google” czy „Firmowe”. Konto możesz dodać na stronie ustawień Konta i synchronizacja. Aplikacje, które proszą o konta niestandardowego typu, będą mogły wyliczać i uwierzytelniać konta tak samo jak w przypadku każdego innego rodzaju konta.

Oczywiście wszystkie te czynności zakładają, że usługa Twojego konta jest zainstalowana na urządzeniu. Jeśli tylko jedna aplikacja będzie miała dostęp do usługi, to nic złego – po prostu umieść tę usługę w pakiecie. Jeśli jednak z Twojej usługi konta będzie korzystać więcej niż jedna aplikacja, wszystko będzie trudniejsze. Nie chcesz dodać tej usługi do wszystkich swoich aplikacji i mieć wiele ich kopii na urządzeniu użytkownika.

Jednym z rozwiązań jest umieszczenie usługi w jednym małym, specjalnym pliku APK. Gdy aplikacja chce korzystać z konta niestandardowego, może sprawdzić na urządzeniu, czy dostępna jest usługa Twojego konta niestandardowego. Jeśli nie, może przekierować użytkownika do Google Play, z którego może pobrać usługę. Początkowo może się to wydawać sporym problemem, ale w porównaniu z alternatywnym wpisywaniem danych logowania w każdej aplikacji korzystającej z konta niestandardowego jest bardzo proste.