App für AutoFill optimieren

Apps, die Standardansichten verwenden, funktionieren mit dem Autofill-Framework, ohne dass eine spezielle Konfiguration erforderlich ist. Sie können auch optimieren, wie Ihre App mit dem Framework funktioniert.

Autofill-Umgebung einrichten

In diesem Abschnitt wird beschrieben, wie Sie die grundlegende Autofill-Funktion für Ihre App einrichten.

Autofill-Dienst konfigurieren

Damit Ihre App das Autofill-Framework verwenden kann, muss auf Ihrem Gerät ein Autofill-Service konfiguriert sein. Die meisten Smartphones und Tablets mit Android 8.0 (API-Level 26) und höher werden mit einem Autofill-Dienst ausgeliefert. Wir empfehlen jedoch, beim Testen Ihrer App einen Testdienst zu verwenden, z. B. den Autofill-Dienst im Android Autofill Framework-Beispiel. Wenn Sie einen Emulator verwenden, legen Sie explizit einen Dienst für automatisches Ausfüllen fest, da der Emulator möglicherweise keinen Standarddienst enthält.

Nachdem Sie den Testdienst für das automatische Ausfüllen über die Beispiel-App installiert haben, aktivieren Sie ihn unter Einstellungen > System > Sprachen & Eingabe > Erweitert > Eingabehilfe > AutoFill-Dienst.

Weitere Informationen zum Konfigurieren eines Emulators zum Testen von Autofill finden Sie unter Autofill in Ihrer App testen.

Hinweise für Autofill geben

Der Autofill-Dienst bestimmt den Typ jeder Ansicht mithilfe von Heuristiken. Wenn Ihre App jedoch auf diesen Heuristiken basiert, kann sich das Verhalten der automatischen Vervollständigung unerwartet ändern, wenn Sie Ihre App aktualisieren. Damit der Dienst zur automatischen Vervollständigung die Formfaktoren Ihrer App richtig erkennt, sollten Sie Hinweise zur automatischen Vervollständigung angeben.

Sie können Autofill-Hinweise mit dem Attribut android:autofillHints festlegen. Im folgenden Beispiel wird ein "password"-Hinweis für ein EditText festgelegt:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:autofillHints="password" />

Sie können Hinweise auch programmatisch mit der Methode setAutofillHints() festlegen, wie im folgenden Beispiel gezeigt:

Kotlin

val password = findViewById<EditText>(R.id.password)
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)

Java

EditText password = findViewById(R.id.password);
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);

Vordefinierte Hinweiskonstanten einschließen

Das Autofill-Framework validiert keine Hinweise. Sie werden ohne Änderung oder Validierung an den Autofill-Dienst übergeben. Sie können zwar einen beliebigen Wert verwenden, aber die Klassen View und AndroidX HintConstants enthalten Listen mit offiziell unterstützten Hinweiskonstanten.

Mithilfe einer Kombination dieser Konstanten können Sie Layouts für häufige Autofill-Szenarien erstellen:

Kontoanmeldedaten

In einem Anmeldeformular können Sie Hinweise zu Anmeldedaten wie AUTOFILL_HINT_USERNAME und AUTOFILL_HINT_PASSWORD einfügen.

Wenn Sie ein neues Konto erstellen oder Nutzer ihren Nutzernamen und ihr Passwort ändern, können Sie AUTOFILL_HINT_NEW_USERNAME und AUTOFILL_HINT_NEW_PASSWORD verwenden.

Kreditkartendaten

Wenn Sie Kreditkarteninformationen anfordern, können Sie Hinweise wie AUTOFILL_HINT_CREDIT_CARD_NUMBER und AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE verwenden.

Führen Sie für das Ablaufdatum der Kreditkarte einen der folgenden Schritte aus:

Anschrift

Für Formularfelder für physische Adressen können Sie Hinweise wie die folgenden verwenden:

Namen von Personen

Wenn Sie Namen von Personen anfordern, können Sie Hinweise wie die folgenden verwenden:

Telefonnummern

Für Telefonnummern können Sie Folgendes verwenden:

Einmalpasswort (OTP)

Für ein Einmalpasswort in einer einzelnen Ansicht können Sie AUTOFILL_HINT_SMS_OTP verwenden.

Wenn Sie mehrere Ansichten haben, die jeweils einer Ziffer des Einmalpassworts entsprechen, können Sie mit der Methode generateSmsOtpHintForCharacterPosition() Hinweise für einzelne Zeichen generieren.

Website- und App-Daten verknüpfen

Autofill-Dienste wie „Autofill mit Google“ können Nutzeranmeldedaten zwischen Browsern und Android-Geräten austauschen, nachdem die App und eine Website verknüpft wurden. Wenn ein Nutzer auf beiden Plattformen denselben Autofill-Dienst auswählt, werden seine Anmeldedaten für Autofill verfügbar, wenn er sich in Ihrer entsprechenden Android-App anmeldet.

Wenn Sie Ihre Android-App mit Ihrer Website verknüpfen möchten, hosten Sie einen Digital Asset Link mit der Beziehung delegate_permission/common.get_login_creds auf Ihrer Website. Deklarieren Sie dann die Verknüpfung in der Datei AndroidManifest.xml Ihrer App. Eine detaillierte Anleitung dazu, wie Sie Ihre Website mit Ihrer Android-App verknüpfen, finden Sie unter Automatisches Log-in für Apps und Websites aktivieren.

Workflow zum automatischen Ausfüllen abschließen

In diesem Abschnitt werden spezifische Szenarien beschrieben, in denen Sie Maßnahmen ergreifen können, um die Autofill-Funktion für Nutzer Ihrer App zu verbessern.

Prüfen, ob das automatische Ausfüllen aktiviert ist

Nutzer können das automatische Ausfüllen aktivieren oder deaktivieren und den Dienst für das automatische Ausfüllen ändern, indem sie zu den Einstellungen > System > Sprachen & Eingabe > Erweitert > Eingabehilfe > Dienst für automatisches Ausfüllen gehen. Ihre App kann die Autofill-Einstellungen des Nutzers nicht überschreiben. Sie können jedoch zusätzliche Autofill-Funktionen in Ihrer App oder in bestimmten Ansichten Ihrer App implementieren, wenn Autofill für den Nutzer verfügbar ist.

Beispiel: TextView zeigt einen Autofill-Eintrag im Überlaufmenü an, wenn Autofill für den Nutzer aktiviert ist. Rufen Sie die Methode isEnabled() des Objekts AutofillManager auf, um zu prüfen, ob die automatische Vervollständigung für den Nutzer aktiviert ist.

Wenn Sie die One Tap-Anmeldung implementieren, können Sie dafür sorgen, dass die Registrierung und Anmeldung auch für Nutzer ohne Autofill optimiert ist.

Autofill-Anfrage erzwingen

Manchmal müssen Sie erzwingen, dass eine Anfrage zum automatischen Ausfüllen als Reaktion auf eine Nutzeraktion erfolgt. Beispiel: TextView bietet ein Menüelement für das automatische Ausfüllen, wenn der Nutzer die Ansicht berührt und hält. Das folgende Codebeispiel zeigt, wie Sie eine Autofill-Anfrage erzwingen:

Kotlin

fun eventHandler(view: View) {
    val afm = requireContext().getSystemService(AutofillManager::class.java)
    afm?.requestAutofill(view)
}

Java

public void eventHandler(View view) {
    AutofillManager afm = context.getSystemService(AutofillManager.class);
    if (afm != null) {
        afm.requestAutofill(view);
    }
}

Sie können auch die Methode cancel() verwenden, um den aktuellen Kontext für das automatische Ausfüllen zu beenden. Das kann nützlich sein, wenn Sie eine Schaltfläche haben, mit der die Felder auf einer Anmeldeseite gelöscht werden.

Den richtigen Typ für das automatische Ausfüllen für Daten in Auswahlsteuerelementen verwenden

Auswahlfelder können bei der automatischen Vervollständigung nützlich sein, da sie eine Benutzeroberfläche bieten, mit der Nutzer den Wert eines Felds ändern können, in dem Datums- oder Zeitdaten gespeichert sind. In einem Kreditkartenformular können Nutzer mit einer Datumsauswahl beispielsweise das Ablaufdatum ihrer Kreditkarte eingeben oder ändern. Sie müssen jedoch eine andere Ansicht, z. B. EditText, verwenden, um die Daten anzuzeigen, wenn die Auswahl nicht sichtbar ist.

Ein EditText-Objekt erwartet nativ Autofill-Daten vom Typ AUTOFILL_TYPE_TEXT. Wenn Sie einen anderen Datentyp verwenden, erstellen Sie eine benutzerdefinierte Ansicht, die von EditText abgeleitet wird und die Methoden implementiert, die zum Verarbeiten des entsprechenden Datentyps erforderlich sind. Wenn Sie beispielsweise ein Datumsfeld haben, implementieren Sie die Methoden mit einer Logik, die Werte vom Typ AUTOFILL_TYPE_DATE richtig verarbeitet.

Wenn Sie den Datentyp für das automatische Ausfüllen angeben, kann der Dienst zum automatischen Ausfüllen eine geeignete Darstellung der in der Ansicht angezeigten Daten erstellen. Weitere Informationen finden Sie unter Auswahlfelder mit Autofill verwenden.

Autofill-Kontext abschließen

Das Autofill-Framework speichert Nutzereingaben für die zukünftige Verwendung, indem nach Abschluss des Autofill-Kontexts ein Dialogfeld „Für Autofill speichern?“ angezeigt wird. Normalerweise ist der Kontext für das automatische Ausfüllen abgeschlossen, wenn eine Aktivität beendet wird. In einigen Situationen müssen Sie das Framework jedoch explizit benachrichtigen, z. B. wenn Sie dieselbe Aktivität, aber unterschiedliche Fragmente für Ihre Anmelde- und Inhaltsbildschirme verwenden. In diesen Fällen können Sie den Kontext explizit beenden, indem Sie AutofillManager.commit() aufrufen.

Unterstützung für benutzerdefinierte Ansichten

In benutzerdefinierten Ansichten kann mit der Autofill API angegeben werden, welche Metadaten für das Autofill-Framework verfügbar gemacht werden. Einige Ansichten fungieren als Container für virtuelle untergeordnete Elemente, z. B. Ansichten, die mit OpenGL gerenderte Benutzeroberflächen enthalten. In diesen Ansichten muss die Struktur der in der App verwendeten Informationen über die API angegeben werden, bevor sie mit dem Autofill-Framework funktionieren können.

Wenn Ihre App benutzerdefinierte Ansichten verwendet, sollten Sie die folgenden Szenarien berücksichtigen:

  • Die benutzerdefinierte Ansicht bietet eine Standardansichtsstruktur oder eine Standardansichtsstruktur.
  • Die benutzerdefinierte Ansicht hat eine virtuelle Struktur oder eine Ansichtsstruktur, die für das Autofill-Framework nicht verfügbar ist.

Benutzerdefinierte Ansichten mit Standardansichtsstruktur

In benutzerdefinierten Ansichten kann festgelegt werden, welche Metadaten für die Autofill-Funktion erforderlich sind. Achten Sie darauf, dass Ihre benutzerdefinierte Ansicht die Metadaten so verwaltet, dass sie mit dem Autofill-Framework kompatibel ist. In Ihrer benutzerdefinierten Ansicht müssen die folgenden Aktionen ausgeführt werden:

  • Den Autofill-Wert verarbeiten, den das Framework an Ihre App sendet.
  • Geben Sie den Typ und den Wert für die automatische Vervollständigung an das Framework weiter.

Wenn die automatische Vervollständigung ausgelöst wird, ruft das Framework für die automatische Vervollständigung autofill() für Ihre Ansicht auf und sendet den Wert, den Ihre Ansicht verwenden muss. Implementieren Sie autofill(), um anzugeben, wie Ihre benutzerdefinierte Ansicht den Wert für das automatische Ausfüllen verarbeitet.

In der Ansicht müssen Sie einen AutoFill-Typ und -Wert angeben, indem Sie die Methoden getAutofillType() und getAutofillValue() überschreiben.

Schließlich darf die automatische Vervollständigung die Ansicht nicht ausfüllen, wenn der Nutzer im aktuellen Zustand keinen Wert für die Ansicht angeben kann, z. B. wenn die Ansicht deaktiviert ist. In diesen Fällen muss getAutofillType() AUTOFILL_TYPE_NONE zurückgeben, getAutofillValue() muss null zurückgeben und autofill() muss nichts tun.

In den folgenden Fällen sind zusätzliche Schritte erforderlich, damit das Framework richtig funktioniert:

  • Die benutzerdefinierte Ansicht kann bearbeitet werden.
  • Die benutzerdefinierte Ansicht enthält vertrauliche Daten.

Die benutzerdefinierte Ansicht kann bearbeitet werden.

Wenn die Ansicht bearbeitbar ist, benachrichtigen Sie das Autofill-Framework über Änderungen, indem Sie notifyValueChanged() für das AutofillManager-Objekt aufrufen.

Die benutzerdefinierte Ansicht enthält vertrauliche Daten

Wenn eine Ansicht personenidentifizierbare Informationen wie E-Mail-Adressen, Kreditkartennummern und Passwörter enthält, muss sie als vertraulich gekennzeichnet werden.

Im Allgemeinen enthalten Ansichten, deren Inhalt aus statischen Ressourcen stammt, keine sensiblen Daten. Ansichten, deren Inhalt dynamisch festgelegt wird, können jedoch sensible Daten enthalten. Ein Label mit dem Text Geben Sie Ihren Nutzernamen ein enthält beispielsweise keine vertraulichen Daten, ein Label mit dem Text Hallo, Max hingegen schon.

Das Autofill-Framework geht standardmäßig davon aus, dass alle Daten vertraulich sind. Sie können Daten, die nicht sensibel sind, entsprechend kennzeichnen.

Wenn Sie angeben möchten, ob eine Ansicht vertrauliche Daten enthält, implementieren Sie onProvideAutofillStructure() und rufen Sie setDataIsSensitive() für das ViewStructure-Objekt auf.

Das folgende Codebeispiel zeigt, wie Sie die Daten in der Ansichtsstruktur als nicht vertraulich kennzeichnen:

Kotlin

override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) {
    super.onProvideAutofillStructure(structure, flags)

    structure.setDataIsSensitive(false)
}

Java

@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
    super.onProvideAutofillStructure(structure, flags);

    structure.setDataIsSensitive(false);
}

Wenn für eine Ansicht nur vordefinierte Werte zulässig sind, können Sie mit der Methode setAutofillOptions() die Optionen festlegen, die zum automatischen Ausfüllen der Ansicht verwendet werden können. Insbesondere Ansichten, deren Typ für das automatische Ausfüllen AUTOFILL_TYPE_LIST ist, müssen diese Methode verwenden, da der Dienst für das automatische Ausfüllen besser funktioniert, wenn er die Optionen kennt, die zum Ausfüllen der Ansicht verfügbar sind.

Ansichten, für die ein Adapter verwendet wird, z. B. ein Spinner, sind ein ähnlicher Fall. Ein Beispiel: Ein Auswahlfeld, das dynamisch erstellte Jahreszahlen basierend auf dem aktuellen Jahr für die Verwendung in Feldern für das Ablaufdatum von Kreditkarten bereitstellt, kann die Methode getAutofillOptions() der Schnittstelle Adapter implementieren, um eine Liste von Jahren bereitzustellen.

Ansichten, in denen ArrayAdapter verwendet wird, können auch Listen mit Werten enthalten. ArrayAdapter legt automatisch Optionen für das automatische Ausfüllen für statische Ressourcen fest. Wenn Sie die Werte dynamisch angeben, überschreiben Sie getAutofillOptions().

Benutzerdefinierte Ansichten mit virtueller Struktur

Für das Autofill-Framework ist eine Ansichtsstruktur erforderlich, bevor es die Informationen in der Benutzeroberfläche Ihrer App bearbeiten und speichern kann. Die Ansichtsstruktur ist für das Framework in den folgenden Situationen nicht verfügbar:

  • Die App verwendet eine Rendering-Engine auf niedriger Ebene, z. B. OpenGL, um die Benutzeroberfläche zu rendern.
  • In der App wird eine Instanz von Canvas verwendet, um die Benutzeroberfläche zu rendern.

In diesen Fällen können Sie eine Ansichtsstruktur angeben, indem Sie onProvideAutofillVirtualStructure() implementieren und so vorgehen:

  1. Erhöhen Sie die Anzahl der untergeordneten Elemente der Ansichtsstruktur durch Aufrufen von addChildCount().
  2. Fügen Sie ein Kind hinzu, indem Sie newChild() aufrufen.
  3. Legen Sie die ID für das automatische Ausfüllen für das untergeordnete Element fest, indem Sie setAutofillId() aufrufen.
  4. Legen Sie relevante Attribute wie den Wert und den Typ für das automatische Ausfüllen fest.
  5. Wenn die Daten im virtuellen Kind vertraulich sind, übergeben Sie true an setDataIsSensitive(). Andernfalls übergeben Sie false.

Das folgende Code-Snippet zeigt, wie ein neues untergeordnetes Element in der virtuellen Struktur erstellt wird:

Kotlin

override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) {

    super.onProvideAutofillVirtualStructure(structure, flags)

    // Create a new child in the virtual structure.
    structure.addChildCount(1)
    val child = structure.newChild(childIndex)

    // Set the autofill ID for the child.
    child.setAutofillId(structure.autofillId!!, childVirtualId)

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue)
    child.setAutofillType(childAutofillType)

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    val childAutofillOptions = arrayOf<CharSequence>("option1", "option2")
    child.setAutofillOptions(childAutofillOptions)

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    val sensitive = !contentIsSetFromResources()
    child.setDataIsSensitive(sensitive)
}

Java

@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {

    super.onProvideAutofillVirtualStructure(structure, flags);

    // Create a new child in the virtual structure.
    structure.addChildCount(1);
    ViewStructure child =
            structure.newChild(childIndex);

    // Set the autofill ID for the child.
    child.setAutofillId(structure.getAutofillId(), childVirtualId);

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue);
    child.setAutofillType(childAutofillType);

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    boolean sensitive = !contentIsSetFromResources();
    child.setDataIsSensitive(sensitive);
}

Wenn sich Elemente in einer virtuellen Struktur ändern, benachrichtigen Sie das Framework, indem Sie die folgenden Aufgaben ausführen:

  • Wenn sich der Fokus in den untergeordneten Elementen ändert, rufen Sie notifyViewEntered() und notifyViewExited() für das AutofillManager-Objekt auf.
  • Wenn sich der Wert eines untergeordneten Elements ändert, rufen Sie notifyValueChanged() für das AutofillManager-Objekt auf.
  • Wenn die Ansichtshierarchie nicht mehr verfügbar ist, weil der Nutzer einen Schritt im Workflow abgeschlossen hat, z. B. wenn er sich über ein Anmeldeformular anmeldet, rufen Sie commit() für das AutofillManager-Objekt auf.
  • Wenn die Ansichtshierarchie ungültig ist, weil der Nutzer einen Schritt im Workflow abgebrochen hat, z. B. wenn er auf eine Schaltfläche tippt, mit der ein Anmeldeformular gelöscht wird, rufen Sie cancel() für das AutofillManager-Objekt auf.

Rückrufe für Autofill-Ereignisse verwenden

Wenn Ihre App eigene Ansichten für die automatische Vervollständigung bereitstellt, benötigen Sie einen Mechanismus, der der App mitteilt, dass die Ansichten als Reaktion auf Änderungen der UI-Funktion für die automatische Vervollständigung aktiviert oder deaktiviert werden sollen. Das AutoFill-Framework bietet diesen Mechanismus in Form von AutofillCallback.

Diese Klasse stellt die Methode onAutofillEvent(View, int) bereit, die von der App aufgerufen wird, nachdem sich der mit einer Ansicht verknüpfte Status für das automatische Ausfüllen geändert hat. Es gibt auch eine überladene Version dieser Methode, die einen childId-Parameter enthält, den Ihre App mit virtuellen Ansichten verwenden kann. Die verfügbaren Status werden im Callback als Konstanten definiert.

Sie können einen Callback mit der Methode registerCallback() der Klasse AutofillManager registrieren. Im folgenden Codebeispiel sehen Sie, wie Sie einen Callback für Autofill-Ereignisse deklarieren:

Kotlin

val afm = context.getSystemService(AutofillManager::class.java)

afm?.registerCallback(object : AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    override fun onAutofillEvent(view: View, event: Int) {
        super.onAutofillEvent(view, event)
        when (event) {
            EVENT_INPUT_HIDDEN -> {
                // The autofill affordance associated with the view was hidden.
            }
            EVENT_INPUT_SHOWN -> {
                // The autofill affordance associated with the view was shown.
            }
            EVENT_INPUT_UNAVAILABLE -> {
                // Autofill isn't available.
            }
        }

    }
})

Java

AutofillManager afm = getContext().getSystemService(AutofillManager.class);

afm.registerCallback(new AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    @Override
    public void onAutofillEvent(@NonNull View view, int event) {
        super.onAutofillEvent(view, event);
        switch (event) {
            case EVENT_INPUT_HIDDEN:
                // The autofill affordance associated with the view was hidden.
                break;
            case EVENT_INPUT_SHOWN:
                // The autofill affordance associated with the view was shown.
                break;
            case EVENT_INPUT_UNAVAILABLE:
                // Autofill isn't available.
                break;
        }
    }
});

Wenn es an der Zeit ist, den Callback zu entfernen, verwenden Sie die Methode unregisterCallback().

Hervorgehobene Drawable für die automatische Vervollständigung anpassen

Wenn eine Ansicht automatisch ausgefüllt wird, rendert die Plattform ein Drawable über der Ansicht, um darauf hinzuweisen, dass die Inhalte der Ansicht automatisch ausgefüllt wurden. Standardmäßig ist dieses Drawable ein solides Rechteck mit einer durchscheinenden Farbe, die etwas dunkler ist als die Farbe des Designs, die zum Zeichnen von Hintergründen verwendet wird. Das Drawable muss nicht geändert werden, kann aber angepasst werden, indem das android:autofilledHighlight-Element des Designs überschrieben wird, das von der Anwendung oder Aktivität verwendet wird. Hier ein Beispiel:

res/values/styles.xml

<resources>
    <style name="MyAutofilledHighlight" parent="...">
        <item name="android:autofilledHighlight">@drawable/my_drawable</item>
    </style>
</resources>

res/drawable/my_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#4DFF0000" />
</shape>

AndroidManifest.xml

<application ...
    android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
    android:theme="@style/MyAutofilledHighlight">

Für das automatische Ausfüllen authentifizieren

Ein Autofill-Dienst kann vom Nutzer eine Authentifizierung verlangen, bevor er Felder in Ihrer App ausfüllen kann. In diesem Fall startet das Android-System die Authentifizierungsaktivität des Dienstes als Teil des Aktivitätsstacks Ihrer Aktivität.

Sie müssen Ihre App nicht aktualisieren, um die Authentifizierung zu unterstützen, da die Authentifizierung im Dienst erfolgt. Sie müssen jedoch dafür sorgen, dass die Ansichtsstruktur der Aktivität beim Neustart der Aktivität beibehalten wird, z. B. indem Sie die Ansichtsstruktur in onCreate() und nicht in onStart() oder onResume() erstellen.

Sie können überprüfen, wie sich Ihre App verhält, wenn ein Autofill-Dienst eine Authentifizierung erfordert. Verwenden Sie dazu den HeuristicsService aus dem AutofillFramework-Beispiel und konfigurieren Sie ihn so, dass eine Authentifizierung der Fill-Antwort erforderlich ist. Sie können dieses Problem auch mit dem BadViewStructureCreationSignInActivity-Beispiel simulieren.

Autofill-IDs für wiederverwendete Ansichten zuweisen

Container, die Ansichten wiederverwenden, z. B. die Klasse RecyclerView, sind nützlich für Apps, in denen auf Grundlage großer Datensätze scrollende Listen von Elementen angezeigt werden müssen. Wenn der Container gescrollt wird, verwendet das System Ansichten im Layout wieder, die dann neuen Inhalt enthalten.

Wenn die ursprünglichen Inhalte einer wiederverwendeten Ansicht ausgefüllt werden, behält der Autofill-Dienst die logische Bedeutung der Ansichten anhand ihrer Autofill-IDs bei. Ein Problem tritt auf, wenn das System die Ansichten im Layout wiederverwendet und die logischen IDs der Ansichten gleich bleiben. Dadurch werden die falschen Autofill-Nutzerdaten einer Autofill-ID zugeordnet.

Um dieses Problem auf Geräten mit Android 9 (API-Level 28) und höher zu beheben, müssen Sie die Autofill-ID von Ansichten, die von RecyclerView verwendet werden, mit den folgenden Methoden explizit verwalten:

  • Die Methode getNextAutofillId() ruft eine neue Autofill-ID ab, die für die Aktivität eindeutig ist.
  • Mit der Methode setAutofillId() wird die eindeutige, logische Autofill-ID dieser Ansicht in der Aktivität festgelegt.

Bekannte Probleme beheben

In diesem Abschnitt werden Problemumgehungen für bekannte Probleme im Autofill-Framework beschrieben.

Autofill führt zum Absturz von Apps unter Android 8.0 und 8.1

Unter Android 8.0 (API-Level 26) und Android 8.1 (API-Level 27) kann die Funktion „Automatisch ausfüllen“ in bestimmten Szenarien dazu führen, dass Ihre App abstürzt. Um potenzielle Probleme zu vermeiden, sollten Sie alle Ansichten, die nicht automatisch ausgefüllt werden, mit importantForAutofill=no taggen. Sie können auch die gesamte Aktivität mit importantForAutofill=noExcludeDescendants taggen.

Größenänderungen von Dialogfeldern werden bei AutoFill nicht berücksichtigt

Unter Android 8.1 (API-Ebene 27) und niedriger wird eine Ansicht in einem Dialogfeld, die nach der Anzeige in der Größe geändert wird, nicht für die automatische Vervollständigung berücksichtigt. Diese Ansichten sind nicht im AssistStructure-Objekt enthalten, das das Android-System an den Autofill-Dienst sendet. Daher kann der Dienst die Ansichten nicht ausfüllen.

Um dieses Problem zu umgehen, ersetzen Sie die Eigenschaft token der Dialogfensterparameter durch die Eigenschaft token der Aktivität, die den Dialog erstellt. Nachdem Sie bestätigt haben, dass die automatische Vervollständigung aktiviert ist, speichern Sie die Fensterparameter in der Methode onWindowAttributesChanged() der Klasse, die von Dialog abgeleitet wird. Ersetzen Sie dann das Attribut token der gespeicherten Parameter durch das Attribut token der übergeordneten Aktivität in der Methode onAttachedToWindow().

Das folgende Code-Snippet zeigt eine Klasse, die diesen Workaround implementiert:

Kotlin

class MyDialog(context: Context) : Dialog(context) {

    // Used to store the dialog window parameters.
    private var token: IBinder? = null

    private val isDialogResizedWorkaroundRequired: Boolean
        get() {
            if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                return false
            }
            val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                context.getSystemService(AutofillManager::class.java)
            } else {
                null
            }
            return autofillManager?.isEnabled ?: false
        }

    override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) {
        if (params.token == null && token != null) {
            params.token = token
        }

        super.onWindowAttributesChanged(params)
    }

    override fun onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired) {
            token = ownerActivity!!.window.attributes.token
        }

        super.onAttachedToWindow()
    }

}

Java

public class MyDialog extends Dialog {

    public MyDialog(Context context) {
        super(context);
    }

    // Used to store the dialog window parameters.
    private IBinder token;

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (params.token == null && token != null) {
            params.token = token;
        }

        super.onWindowAttributesChanged(params);
    }

    @Override
    public void onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired()) {
            token = getOwnerActivity().getWindow().getAttributes().token;
        }

        super.onAttachedToWindow();
    }

    private boolean isDialogResizedWorkaroundRequired() {
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O
                || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
            return false;
        }
        AutofillManager autofillManager =
                null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            autofillManager = getContext().getSystemService(AutofillManager.class);
        }
        return autofillManager != null && autofillManager.isEnabled();
    }

}

Um unnötige Vorgänge zu vermeiden, zeigt das folgende Code-Snippet, wie Sie prüfen können, ob AutoFill auf dem Gerät unterstützt und für den aktuellen Nutzer aktiviert ist und ob dieser Workaround erforderlich ist:

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, check whether the
    // workaround is still required for the current device.
    return isAutofillAvailable()
}

fun Context.isAutofillAvailable(): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // The autofill framework is available on Android 8.0
        // or higher.
        return false
    }

    val afm = getSystemService(AutofillManager::class.java)
    // Return true if autofill is supported by the device and enabled
    // for the current user.
    return afm != null && afm.isEnabled
}

Java

public class AutofillHelper {

    public static boolean isDialogResizedWorkaroundRequired(Context context) {
        // After the issue is resolved on Android, check whether the
        // workaround is still required for the current device.
        return isAutofillAvailable(context);
    }

    public static boolean isAutofillAvailable(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // The autofill framework is available on Android 8.0
            // or higher.
            return false;
        }

        AutofillManager afm = context.getSystemService(AutofillManager.class);
        // Return true if autofill is supported by the device and enabled
        // for the current user.
        return afm != null && afm.isEnabled();
    }
}

App mit Autofill testen

Nachdem Sie Ihre App für die Verwendung mit AutoFill-Diensten optimiert haben, sollten Sie testen, ob sie wie vorgesehen mit AutoFill-Diensten funktioniert.

Verwenden Sie zum Testen Ihrer App einen Emulator oder ein physisches Gerät mit Android 8.0 (API-Level 26) oder höher. Weitere Informationen zum Erstellen eines Emulators finden Sie unter Virtuelle Geräte erstellen und verwalten.

Autofill-Service installieren

Bevor Sie Ihre App mit Autofill testen können, müssen Sie eine andere App installieren, die Autofill-Dienste bereitstellt. Sie können dazu eine Drittanbieter-App verwenden. Es ist jedoch einfacher, einen Autofill-Beispieldienst zu nutzen, damit Sie sich nicht für Drittanbieterdienste registrieren müssen.

Sie können das Java-Beispiel für das Android-Autofill-Framework verwenden, um Ihre App mit Autofill-Diensten zu testen. Die Beispiel-App bietet einen Autofill-Dienst und Activity-Clientklassen, mit denen Sie den Workflow testen können, bevor Sie ihn mit Ihrer App verwenden. Auf dieser Seite wird auf die Beispiel-App android-AutofillFramework verwiesen.

Nachdem Sie die App installiert haben, aktivieren Sie den Dienst für automatisches Ausfüllen in den Systemeinstellungen des Emulators unter Einstellungen > System > Sprachen und Eingabe > Erweitert > Eingabehilfe > Dienst für automatisches Ausfüllen.

Datenanforderungen analysieren

Wenn Sie Ihre App mit dem Autofill-Dienst testen möchten, muss der Dienst Daten haben, die er zum Ausfüllen Ihrer App verwenden kann. Außerdem muss der Dienst wissen, welche Art von Daten in den Ansichten Ihrer App erwartet wird. Wenn Ihre App beispielsweise eine Ansicht hat, in der ein Nutzername erwartet wird, muss der Dienst einen Datensatz mit einem Nutzernamen und einen Mechanismus haben, um zu wissen, dass in der Ansicht solche Daten erwartet werden.

Legen Sie mit dem Attribut android:autofillHints fest, welche Art von Daten in Ihren Ansichten erwartet wird. Einige Dienste verwenden ausgefeilte Heuristiken, um den Datentyp zu bestimmen. Andere, wie die Beispiel-App, sind darauf angewiesen, dass der Entwickler diese Informationen bereitstellt. Ihre App funktioniert besser mit AutoFill-Diensten, wenn Sie das Attribut android:autofillHints in den Ansichten festlegen, die für AutoFill relevant sind.

Test ausführen

Nachdem Sie die Datenanforderungen analysiert haben, können Sie den Test ausführen. Dazu müssen Sie Testdaten im Autofill-Dienst speichern und Autofill in Ihrer App auslösen.

Daten im Dienst speichern

So speichern Sie Daten im aktuell aktiven Autofill-Service:

  1. Öffnen Sie eine App mit einer Ansicht, für die der Datentyp erforderlich ist, den Sie für den Test verwenden möchten. Die Beispiel-App android-AutofillFramework stellt die Benutzeroberfläche mit Ansichten bereit, in denen verschiedene Datentypen erwartet werden, z. B. Kreditkartennummern und Nutzernamen.
  2. Tippen Sie auf die Ansicht, die den benötigten Datentyp enthält.
  3. Geben Sie einen Wert in die Ansicht ein.
  4. Tippen Sie auf die Bestätigungsschaltfläche, z. B. Anmelden oder Senden. Normalerweise müssen Sie das Formular einreichen, bevor der Dienst die Daten speichert.
  5. Bestätigen Sie die Berechtigungsanfrage im Systemdialogfeld. Im Systemdialogfeld wird der Name des derzeit aktiven Dienstes angezeigt und Sie werden gefragt, ob Sie diesen Dienst für Ihren Test verwenden möchten. Wenn Sie den Dienst verwenden möchten, tippen Sie auf Speichern.

Wenn Android das Berechtigungsdialogfeld nicht anzeigt oder der Dienst nicht der ist, den Sie in Ihrem Test verwenden möchten, prüfen Sie, ob der Dienst derzeit in den Systemeinstellungen aktiv ist.

AutoFill in Ihrer App auslösen

So lösen Sie die automatische Vervollständigung in Ihrer App aus:

  1. Öffnen Sie Ihre App und rufen Sie die Aktivität auf, die die Ansichten enthält, die Sie testen möchten.
  2. Tippen Sie auf die Ansicht, die ausgefüllt werden muss.
  3. Das System zeigt die Benutzeroberfläche für das automatische Ausfüllen an, die die Datasets enthält, mit denen die Ansicht ausgefüllt werden kann (siehe Abbildung 1).
  4. Tippen Sie auf das Dataset mit den Daten, die Sie verwenden möchten. In der Ansicht werden die Daten angezeigt, die zuvor im Dienst gespeichert waren.
Autofill-Benutzeroberfläche mit „dataset-2“ als verfügbarem Dataset
Abbildung 1. AutoFill-Benutzeroberfläche mit verfügbaren Datasets

Wenn die Autofill-Benutzeroberfläche unter Android nicht angezeigt wird, können Sie Folgendes versuchen:

  • Prüfen Sie, ob in den Ansichten Ihrer App der richtige Wert für das Attribut android:autofillHints verwendet wird. Eine Liste der möglichen Werte für das Attribut finden Sie in der Klasse View unter den Konstanten mit dem Präfix AUTOFILL_HINT.
  • Prüfen Sie, ob das Attribut android:importantForAutofill für die Ansicht, die ausgefüllt werden muss, auf einen anderen Wert als no festgelegt ist. Alternativ kann es auch für die Ansicht oder eines ihrer übergeordneten Elemente auf einen anderen Wert als noExcludeDescendants festgelegt sein.