Stub-Authenticator erstellen

Das Synchronisierungsadapter-Framework geht davon aus, dass Ihr Synchronisierungsadapter Daten zwischen dem mit einem Konto verknüpften Gerätespeicher und einem Serverspeicher überträgt, für den Anmeldezugriff erforderlich ist. Aus diesem Grund erwartet das Framework, dass Sie eine Komponente, die als Authenticator bezeichnet wird, als Teil Ihres Synchronisierungsadapters bereitstellen. Diese Komponente ist in das Android-Konten- und Authentifizierungs-Framework eingebunden und bietet eine Standardschnittstelle für die Verarbeitung von Nutzeranmeldedaten wie Anmeldedaten.

Auch wenn für Ihre App keine Konten verwendet werden, müssen Sie eine Authentifizierungskomponente bereitstellen. Wenn Sie keine Konten oder Serveranmeldungen verwenden, werden die vom Authenticator verarbeiteten Informationen ignoriert, sodass Sie eine Authentifizierungskomponente bereitstellen können, die Implementierungen der Stub-Methode enthält. Sie müssen außerdem eine gebundene Service angeben, mit der das Framework des Synchronisierungsadapters die Methoden des Authenticator aufrufen kann.

In dieser Lektion erfahren Sie, wie Sie alle Teile eines Stub-Authenticator definieren, um die Anforderungen des Sync Adapter-Frameworks zu erfüllen. Wenn Sie einen echten Authenticator bereitstellen müssen, der Nutzerkonten verarbeitet, lesen Sie die Referenzdokumentation für AbstractAccountAuthenticator.

Stub-Authenticator-Komponente hinzufügen

Wenn Sie Ihrer App eine Stub-Authentifikatorkomponente hinzufügen möchten, erstellen Sie eine Klasse, die AbstractAccountAuthenticator erweitert, und erstellen Sie dann einen Stub für die erforderlichen Methoden, indem Sie entweder null zurückgeben oder eine Ausnahme auslösen.

Das folgende Snippet zeigt ein Beispiel für eine Stub-Authenticator-Klasse:

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();
    }
}

Binden Sie den Authenticator an das Framework.

Damit das Synchronisierungsadapter-Framework auf Ihren Authenticator zugreifen kann, müssen Sie einen gebundenen Service dafür erstellen. Dieser Dienst stellt ein Android-Binderobjekt zur Verfügung, über das das Framework Ihren Authenticator aufrufen und Daten zwischen dem Authenticator und dem Framework weitergeben kann.

Das folgende Snippet zeigt, wie Sie das gebundene Service definieren:

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();
    }
}

Datei mit Authenticator-Metadaten hinzufügen

Um Ihre Authentifizierungskomponente mit dem Synchronisierungsadapter und den Konto-Frameworks zu verbinden, müssen Sie diesem Framework Metadaten zur Verfügung stellen, die die Komponente beschreiben. In diesen Metadaten wird der Kontotyp, den Sie für den Synchronisierungsadapter erstellt haben, und Elemente der Benutzeroberfläche deklariert, die vom System angezeigt werden, wenn der Kontotyp für den Nutzer sichtbar sein soll. Geben Sie diese Metadaten in einer XML-Datei an, die im Verzeichnis /res/xml/ Ihres Anwendungsprojekts gespeichert ist. Sie können der Datei einen beliebigen Namen geben. Normalerweise heißt sie aber authenticator.xml.

Diese XML-Datei enthält ein einzelnes <account-authenticator>-Element mit den folgenden Attributen:

android:accountType
Im Synchronisierungsadapter-Framework muss jeder Synchronisierungsadapter einen Kontotyp in Form eines Domainnamens haben. Das Framework verwendet den Kontotyp als Teil der internen Identifizierung des Synchronisierungsadapters. Bei Servern, die eine Anmeldung erfordern, wird der Kontotyp zusammen mit einem Nutzerkonto als Teil der Anmeldedaten an den Server gesendet.

Wenn für Ihren Server keine Anmeldung erforderlich ist, müssen Sie trotzdem einen Kontotyp angeben. Verwenden Sie als Wert einen Domainnamen, den Sie kontrollieren. Das Framework verwendet ihn zur Verwaltung Ihres Synchronisierungsadapters, der Wert wird jedoch nicht an Ihren Server gesendet.

android:icon
Zeiger auf eine Drawable-Ressource, die ein Symbol enthält. Wenn Sie den Synchronisierungsadapter durch Angabe des Attributs android:userVisible="true" in res/xml/syncadapter.xml sichtbar machen, müssen Sie diese Symbolressource angeben. Sie wird im Bereich Konten in den Einstellungen des Systems angezeigt.
android:smallIcon
Zeiger auf eine Drawable-Ressource, die eine kleine Version des Symbols enthält. Je nach Bildschirmgröße kann diese Ressource im Abschnitt Konten der Systemeinstellungen des Systems anstelle von android:icon verwendet werden.
android:label
Lokalisierbarer String, der Nutzern den Kontotyp angibt. Wenn Sie den Synchronisierungsadapter durch Angabe des Attributs android:userVisible="true" in res/xml/syncadapter.xml sichtbar machen, sollten Sie diesen String angeben. Es wird im Bereich Konten der Einstellungen-App des Systems neben dem Symbol angezeigt, das Sie für die Authentifizierungs-App definiert haben.

Das folgende Snippet zeigt die XML-Datei für den Authenticator, den Sie zuvor erstellt haben:

<?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"/>

Authenticator im Manifest deklarieren

In einem vorherigen Schritt haben Sie eine gebundene Service erstellt, die die Authentifizierungs-App mit dem Synchronisierungsadapter-Framework verknüpft. Um diesen Dienst im System zu identifizieren, deklarieren Sie ihn in Ihrem App-Manifest, indem Sie das folgende <service>-Element als untergeordnetes Element von <application> hinzufügen:

    <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>

Das Element <intent-filter> richtet einen Filter ein, der von der Intent-Aktion android.accounts.AccountAuthenticator ausgelöst wird, die vom System zum Ausführen des Authenticator gesendet wird. Wenn der Filter ausgelöst wird, startet das System AuthenticatorService, die gebundene Service, die Sie zum Umschließen des Authenticator angegeben haben.

Das Element <meta-data> deklariert die Metadaten für den Authenticator. Das Attribut android:name verknüpft die Metadaten mit dem Authentifizierungs-Framework. Das Element android:resource gibt den Namen der Authenticator-Metadatendatei an, die Sie zuvor erstellt haben.

Neben einem Authenticator ist für einen Synchronisierungsadapter auch ein Contentanbieter erforderlich. Wenn Ihre App noch keinen Contentanbieter verwendet, fahren Sie mit der nächsten Lektion fort, um zu erfahren, wie Sie einen Stub-Contentanbieter erstellen, oder fahren Sie mit der Lektion Synchronisierungsadapter erstellen fort.