Benutzerdefinierten Kontotyp erstellen

Bisher haben wir über den Zugriff auf Google APIs gesprochen, für die von Google definierte Konten und Nutzer verwendet werden. Wenn Sie jedoch einen eigenen Onlinedienst haben, gibt es dafür keine Google-Konten oder Nutzer. Was tun Sie also? Es stellt sich heraus, dass es relativ einfach ist, neue Kontotypen auf dem Gerät eines Nutzers zu installieren. In dieser Lektion wird erläutert, wie Sie einen benutzerdefinierten Kontotyp erstellen, der genauso funktioniert wie die integrierten Konten.

Benutzerdefinierten Kontocode implementieren

Als Erstes benötigen Sie eine Möglichkeit, die Anmeldedaten vom Nutzer zu erhalten. Dies kann einfach ein Dialogfeld sein, in dem Sie nach einem Namen und einem Passwort gefragt werden. Es kann sich aber auch um ein komplexeres Verfahren wie ein Einmalpasswort oder einen biometrischen Scan handeln. In jedem Fall sind Sie dafür verantwortlich, den folgenden Code zu implementieren:

  1. Anmeldedaten des Nutzers erfassen
  2. Die Anmeldedaten werden beim Server authentifiziert.
  3. Speichert die Anmeldedaten auf dem Gerät

Normalerweise können alle drei Anforderungen durch eine Aktivität erfüllt werden. Wir nennen dies Authenticator-Aktivität.

Da sie mit dem AccountManager-System interagieren müssen, haben Authenticator-Aktivitäten bestimmte Anforderungen, die für normale Aktivitäten nicht gelten. Damit Sie die Arbeit erleichtern können, stellt das Android-Framework eine Basisklasse (AccountAuthenticatorActivity) bereit, die Sie erweitern können, um Ihre eigene benutzerdefinierte Authentifizierung zu erstellen.

Wie Sie die ersten beiden Anforderungen einer Authenticator-Aktivität, also das Erfassen von Anmeldedaten und die Authentifizierung, erfüllen, liegt ganz bei Ihnen. (Wenn es nur eine Möglichkeit gäbe, bräuchte es überhaupt keine "benutzerdefinierten" Kontotypen.) Die dritte Anforderung hat eine kanonische und ziemlich einfache Implementierung:

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

Seien Sie schlau, was die Sicherheit angeht!

Beachten Sie, dass AccountManager weder ein Verschlüsselungsdienst noch ein Schlüsselbund ist. Die Anmeldedaten für das Konto werden genau so wie von Ihnen übergeben als Klartext gespeichert. Bei den meisten Geräten ist dies kein besonderes Problem, da sie in einer Datenbank gespeichert werden, die nur für den Root-Zugriff zugänglich ist. Auf einem gerooteten Gerät sind die Anmeldedaten jedoch für alle Nutzer mit adb-Zugriff auf das Gerät lesbar.

Vor diesem Hintergrund sollten Sie das tatsächliche Passwort des Nutzers nicht an AccountManager.addAccountExplicitly() übergeben. Stattdessen sollten Sie ein kryptografisch sicheres Token speichern, das für einen Angreifer nur begrenzt verwendet werden kann. Wenn Ihre Nutzeranmeldedaten etwas Wertvolles schützen, sollten Sie eine ähnliche Vorgehensweise in Betracht ziehen.

Zur Erinnerung:Halte dich beim Thema Sicherheitscode an die „Mythbusters“-Regel: Probier das nicht zu Hause aus! Konsultieren Sie einen Sicherheitsexperten, bevor Sie benutzerdefinierten Kontocode implementieren.

Nachdem Sie die Haftungsausschlüsse für die Sicherheit beseitigt haben, können Sie sich wieder an die Arbeit machen. Sie haben bereits den Teil Ihres benutzerdefinierten Kontocodes implementiert. Jetzt fehlt nur noch die Installation.

AbstrakteAccountAuthenticator-Erweiterung erweitern

Damit AccountManager mit deinem benutzerdefinierten Kontocode funktioniert, benötigst du eine Klasse, die die von AccountManager erwarteten Schnittstellen implementiert. Diese Klasse ist die Authenticator-Klasse.

Am einfachsten können Sie eine Authenticator-Klasse erstellen, indem Sie AbstractAccountAuthenticator erweitern und die abstrakten Methoden implementieren. Wenn Sie die vorherigen Lektionen durchgearbeitet haben, sollten Ihnen die abstrakten Methoden von AbstractAccountAuthenticator bekannt vorkommen. Sie sind die Gegenseite der Methoden, die Sie in der vorherigen Lektion zum Abrufen von Kontoinformationen und Autorisierungstokens aufgerufen haben.

Für die korrekte Implementierung einer Authenticator-Klasse sind mehrere separate Code-Elemente erforderlich. Zuerst enthält AbstractAccountAuthenticator sieben abstrakte Methoden, die Sie überschreiben müssen. Als Nächstes müssen Sie Ihrem Anwendungsmanifest einen Intent-Filter für "android.accounts.AccountAuthenticator" hinzufügen (siehe nächster Abschnitt). Schließlich müssen Sie zwei XML-Ressourcen angeben, die unter anderem den Namen Ihres benutzerdefinierten Kontotyps und das Symbol definieren, das im System neben Konten dieses Typs angezeigt wird.

Eine detaillierte Anleitung zum Implementieren einer erfolgreichen Authentifizierungsklasse und der XML-Dateien finden Sie in der AbstractAccountAuthenticator-Dokumentation.

Wenn für die Authentifizierungsaktivität spezielle Initialisierungsparameter erforderlich sind, können Sie diese mit Intent.putExtra() an den Intent anhängen.

Authentifizierungsdienst erstellen

Da Sie jetzt einen Authentifizierungskurs haben, brauchen Sie einen geeigneten Ort. Kontoauthentifizierungsprogramme müssen für mehrere Anwendungen verfügbar sein und im Hintergrund arbeiten. Daher müssen sie natürlich innerhalb einer Service ausgeführt werden. Wir nennen dies den Authenticator-Dienst.

Der Authentifizierungsdienst kann ganz einfach sein. Dazu müssen Sie lediglich eine Instanz Ihrer Authenticator-Klasse in onCreate() erstellen und getIBinder() in onBind() aufrufen.

Vergessen Sie nicht, der Manifestdatei ein <service>-Tag hinzuzufügen, einen Intent-Filter für den AccountAuthenticator-Intent hinzuzufügen und die Kontoauthentifizierung zu deklarieren:

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

Dienst bereitstellen

Das war's! Das System erkennt jetzt Ihren Kontotyp, zusammen mit allen großen Kontotypen wie "Google" und "Corporate". Auf der Einstellungsseite Konten & Synchronisierung können Sie ein Konto hinzufügen. Apps, die nach Konten Ihres benutzerdefinierten Typs fragen, können diese wie bei jedem anderen Kontotyp aufzählen und authentifizieren.

Dies setzt natürlich voraus, dass Ihr Kontodienst tatsächlich auf dem Gerät installiert ist. Wenn nur eine Anwendung überhaupt auf den Dienst zugreifen wird, ist das kein Problem, bündeln Sie den Dienst einfach in der Anwendung. Wenn Ihr Kontodienst jedoch von mehr als einer Anwendung verwendet werden soll, wird die Sache etwas komplizierter. Sie möchten den Dienst nicht mit all Ihren Apps bündeln und mehrere Kopien davon belegen, die Speicherplatz auf dem Gerät des Nutzers belegen.

Eine Lösung besteht darin, den Dienst in einem kleinen, besonderen APK zu platzieren. Wenn eine App Ihren benutzerdefinierten Kontotyp verwenden möchte, kann sie auf dem Gerät prüfen, ob der Dienst für benutzerdefinierte Konten verfügbar ist. Andernfalls kann der Nutzer zu Google Play weitergeleitet werden, wo er den Dienst herunterladen kann. Das mag zunächst nach einer Menge Probleme erscheinen, aber verglichen mit der Alternative, die Anmeldedaten für jede Anwendung, in der Ihr benutzerdefiniertes Konto verwendet wird, noch einmal einzugeben, ist es ganz einfach.