Tworzenie kodu uwierzytelniającego

Platforma adaptera synchronizacji zakłada, że adapter synchronizacji przenosi dane między pamięcią urządzenia powiązaną z kontem a pamięcią serwera, która wymaga dostępu do logowania. Dlatego platforma oczekuje, że jako część adaptera synchronizacji musisz udostępnić komponent o nazwie uwierzytelniający. Łączy się on z kontami Androida i platformą uwierzytelniania oraz udostępnia standardowy interfejs do obsługi danych logowania użytkownika, takich jak dane logowania.

Nawet jeśli aplikacja nie korzysta z kont, i tak musisz dostarczyć komponent uwierzytelniający. Jeśli nie używasz kont ani logowania na serwer, informacje obsługiwane przez narzędzie uwierzytelniające są ignorowane, dzięki czemu możesz udostępnić komponent uwierzytelniania zawierający implementacje metod wycinka kodu. Musisz też podać powiązany Service, który umożliwia platformie adaptera synchronizacji wywoływanie metod uwierzytelniania.

Z tej lekcji dowiesz się, jak zdefiniować wszystkie części uwierzytelniające, które są potrzebne do spełnienia wymagań platformy adaptera synchronizacji. Jeśli musisz podać prawdziwy mechanizm uwierzytelniający, który obsługuje konta użytkowników, przeczytaj dokumentację AbstractAccountAuthenticator.

Dodaj komponent uwierzytelniający wycinka kodu

Aby dodać do aplikacji komponent uwierzytelniający, utwórz klasę, która rozszerza zakres AbstractAccountAuthenticator, a następnie zrezygnuj z wymaganych metod, zwracając null lub zgłaszając wyjątek.

Ten fragment kodu zawiera przykład klasy uwierzytelniającej skróconej strony:

Kotlin

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
class Authenticator(context: Context) // Simple constructor
    : AbstractAccountAuthenticator(context) {

    // Editing properties is not supported
    override fun editProperties(r: AccountAuthenticatorResponse, s: String): Bundle {
        throw UnsupportedOperationException()
    }

    // Don't add additional accounts
    @Throws(NetworkErrorException::class)
    override fun addAccount(
            r: AccountAuthenticatorResponse,
            s: String,
            s2: String,
            strings: Array<String>,
            bundle: Bundle
    ): Bundle?  = null

    // Ignore attempts to confirm credentials
    @Throws(NetworkErrorException::class)
    override fun confirmCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            bundle: Bundle
    ): Bundle?  = null

    // Getting an authentication token is not supported
    @Throws(NetworkErrorException::class)
    override fun getAuthToken(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Getting a label for the auth token is not supported
    override fun getAuthTokenLabel(s: String): String {
        throw UnsupportedOperationException()
    }

    // Updating user credentials is not supported
    @Throws(NetworkErrorException::class)
    override fun updateCredentials(
            r: AccountAuthenticatorResponse,
            account: Account,
            s: String,
            bundle: Bundle
    ): Bundle {
        throw UnsupportedOperationException()
    }

    // Checking features for the account is not supported
    @Throws(NetworkErrorException::class)
    override fun hasFeatures(
            r: AccountAuthenticatorResponse,
            account: Account,
            strings: Array<String>
    ): Bundle {
        throw UnsupportedOperationException()
    }
}

Java

/*
 * Implement AbstractAccountAuthenticator and stub out all
 * of its methods
 */
public class Authenticator extends AbstractAccountAuthenticator {
    // Simple constructor
    public Authenticator(Context context) {
        super(context);
    }
    // Editing properties is not supported
    @Override
    public Bundle editProperties(
            AccountAuthenticatorResponse r, String s) {
        throw new UnsupportedOperationException();
    }
    // Don't add additional accounts
    @Override
    public Bundle addAccount(
            AccountAuthenticatorResponse r,
            String s,
            String s2,
            String[] strings,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Ignore attempts to confirm credentials
    @Override
    public Bundle confirmCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            Bundle bundle) throws NetworkErrorException {
        return null;
    }
    // Getting an authentication token is not supported
    @Override
    public Bundle getAuthToken(
            AccountAuthenticatorResponse r,
            Account account,
            String s,
            Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Getting a label for the auth token is not supported
    @Override
    public String getAuthTokenLabel(String s) {
        throw new UnsupportedOperationException();
    }
    // Updating user credentials is not supported
    @Override
    public Bundle updateCredentials(
            AccountAuthenticatorResponse r,
            Account account,
            String s, Bundle bundle) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
    // Checking features for the account is not supported
    @Override
    public Bundle hasFeatures(
        AccountAuthenticatorResponse r,
        Account account, String[] strings) throws NetworkErrorException {
        throw new UnsupportedOperationException();
    }
}

Powiąż uwierzytelnianie z platformą

Aby platforma adaptera synchronizacji miała dostęp do uwierzytelniania, musisz utworzyć dla niej powiązaną usługę. Ta usługa udostępnia obiekt powiązania Androida, który umożliwia platformie wywołanie Twojego mechanizmu uwierzytelniania i przekazywanie danych między nim a platformą.

Ten fragment kodu pokazuje, jak zdefiniować granicę Service:

Kotlin

/**
* A bound Service that instantiates the authenticator
* when started.
*/
class AuthenticatorService : Service() {

    // Instance field that stores the authenticator object
    private lateinit var mAuthenticator: Authenticator

    override fun onCreate() {
        // Create a new authenticator object
        mAuthenticator = Authenticator(getApplicationContext())
    }

    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    override fun onBind(intent: Intent?): IBinder = mAuthenticator.iBinder
}

Java

/**
 * A bound Service that instantiates the authenticator
 * when started.
 */
public class AuthenticatorService extends Service {
    ...
    // Instance field that stores the authenticator object
    private Authenticator mAuthenticator;
    @Override
    public void onCreate() {
        // Create a new authenticator object
        mAuthenticator = new Authenticator(getApplicationContext());
    }
    /*
     * When the system binds to this Service to make the RPC call
     * return the authenticator's IBinder.
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mAuthenticator.getIBinder();
    }
}

Dodaj plik metadanych uwierzytelniania

Aby podłączyć komponent uwierzytelniania do adaptera synchronizacji i platform kont, musisz udostępnić tej platformie metadane opisujące ten komponent. Te metadane deklarują typ konta utworzony dla adaptera synchronizacji oraz elementy interfejsu, które wyświetla system, jeśli chcesz, by rodzaj konta był widoczny dla użytkownika. Zadeklaruj te metadane w pliku XML przechowywanym w katalogu /res/xml/ w projekcie aplikacji. Plikowi możesz nadać dowolną nazwę. Zazwyczaj ma on nazwę authenticator.xml.

Ten plik XML zawiera pojedynczy element <account-authenticator> o następujących atrybutach:

android:accountType
Platforma adaptera synchronizacji wymaga, aby każdy adapter synchronizacji miał określony typ konta w postaci nazwy domeny. Platforma używa typu konta do wewnętrznej identyfikacji adaptera synchronizacji. W przypadku serwerów wymagających logowania typ konta wraz z kontem użytkownika jest wysyłany do serwera jako część danych logowania.

Nawet jeśli serwer nie wymaga logowania, musisz podać rodzaj konta. Jako wartość wpisz nazwę domeny, nad którą masz kontrolę. Mimo że platforma używa jej do zarządzania adapterem synchronizacji, wartość nie jest wysyłana do Twojego serwera.

android:icon
Wskaźnik do zasobu Drawable zawierającego ikonę. Jeśli ustawisz adapter synchronizacji jako widoczny, określając atrybut android:userVisible="true" w res/xml/syncadapter.xml, musisz podać ten zasób ikony. Znajdziesz je w sekcji Konta w systemowej aplikacji Ustawienia.
android:smallIcon
Wskaźnik do zasobu Drawable zawierającego małą wersję ikony. W zależności od rozmiaru ekranu można go użyć zamiast android:icon w sekcji Konta w aplikacji Ustawienia systemu.
android:label
Zlokalizowany ciąg znaków, który wskazuje użytkownikom typ konta. Podaj ten ciąg, jeśli ustawisz adapter synchronizacji jako widoczny, określając atrybut android:userVisible="true" w res/xml/syncadapter.xml. Pojawia się ona w sekcji Konta w aplikacji Ustawienia obok ikony zdefiniowanej przez Ciebie dla uwierzytelniania.

Ten fragment kodu zawiera plik XML utworzonego wcześniej mechanizmu uwierzytelniającego:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:accountType="example.com"
        android:icon="@drawable/ic_launcher"
        android:smallIcon="@drawable/ic_launcher"
        android:label="@string/app_name"/>

Zadeklaruj mechanizm uwierzytelniający w pliku manifestu

W poprzednim kroku utworzono powiązany Service, który łączy mechanizm uwierzytelniający z platformą adaptera synchronizacji. Aby zidentyfikować tę usługę w systemie, zadeklaruj ją w manifeście aplikacji, dodając ten element <service> jako element podrzędny <application>:

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

Element <intent-filter> konfiguruje filtr aktywowany przez działanie intencji android.accounts.AccountAuthenticator wysyłane przez system w celu uruchomienia mechanizmu uwierzytelniającego. Po uruchomieniu filtra system uruchamia AuthenticatorService, czyli podaną przez Ciebie ramkę Service, która pakuje mechanizm uwierzytelniający.

Element <meta-data> deklaruje metadane na potrzeby modułu uwierzytelniającego. Atrybut android:name łączy metadane z platformą uwierzytelniania. Element android:resource określa nazwę utworzonego wcześniej pliku metadanych uwierzytelniania.

Adapter synchronizacji wymaga też dostawcy treści. Jeśli Twoja aplikacja nie korzysta jeszcze z dostawcy treści, przejdź do następnej lekcji, aby dowiedzieć się, jak utworzyć dostawcę treści . W przeciwnym razie zapoznaj się z lekcją Tworzenie adaptera synchronizacji.