Aplikacje, które korzystają z widoków standardowych, współpracują z ramami automatycznego wypełniania bez konieczności specjalnej konfiguracji. Możesz też zoptymalizować działanie aplikacji za pomocą frameworka.
Konfigurowanie środowiska autouzupełniania
W tej sekcji opisano, jak skonfigurować w aplikacji podstawowe funkcje autouzupełniania.
Konfigurowanie usługi autouzupełniania
Aby aplikacja mogła korzystać z ramy autouzupełniania, musisz skonfigurować na urządzeniu usługę autouzupełniania. Chociaż większość telefonów i tabletów z Androidem 8.0 (poziom interfejsu API 26) lub nowszym ma zainstalowaną usługę autouzupełniania, podczas testowania aplikacji zalecamy użycie usługi testowej, np. usługi autouzupełniania w ramach przykładowego interfejsu autouzupełniania Androida. Jeśli używasz emulatora, wyraźnie ustaw usługę autouzupełniania, ponieważ emulator może nie mieć domyślnej usługi.
Po zainstalowaniu testowej usługi autouzupełniania z przykładowej aplikacji włącz tę usługę, wybierając Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Asystent wprowadzania > Usługa autouzupełniania.
Więcej informacji o konfigurowaniu emulatora na potrzeby testowania autouzupełniania znajdziesz w artykule Testowanie aplikacji z autouzupełnianiem.
Podawanie wskazówek dotyczących autouzupełniania
Usługa autouzupełniania określa typ każdego widoku za pomocą heurystyk. Jeśli jednak Twoja aplikacja korzysta z tych heurystycznych metod, zachowanie funkcji autouzupełniania może się nieoczekiwanie zmienić po jej zaktualizowaniu. Aby usługa autouzupełniania mogła poprawnie rozpoznawać formaty pól w aplikacji, podaj wskazówki dotyczące autouzupełniania.
Wskazówki autouzupełniania możesz ustawić za pomocą atrybutu android:autofillHints
. W tym przykładzie ustawiamy podpowiedź "password"
dla elementu EditText
:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="password" />
Możesz też skonfigurować podpowiedzi programowo za pomocą metody setAutofillHints()
, jak w tym przykładzie:
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);
Uwzględnij wstępnie zdefiniowane stałe wskazówki
Platforma autouzupełniania nie weryfikuje wskazówek. Są one przekazywane bez zmian i weryfikacji do usługi autouzupełniania. Możesz użyć dowolnej wartości, ale klasy View
i HintConstants
w Androidzie X zawierają listy oficjalnie obsługiwanych stałych wskazówek.
Łącząc te stałe, możesz tworzyć układy na potrzeby typowych scenariuszy autouzupełniania:
Dane logowania do konta
W formularzu logowania możesz dodać wskazówki dotyczące danych logowania do konta, np. AUTOFILL_HINT_USERNAME
czy AUTOFILL_HINT_PASSWORD
.
Do tworzenia nowego konta lub w przypadku, gdy użytkownicy zmieniają nazwę użytkownika i hasło, możesz użyć funkcji AUTOFILL_HINT_NEW_USERNAME
i AUTOFILL_HINT_NEW_PASSWORD
.
Informacje o karcie kredytowej
Podczas wysyłania żądania informacji o karcie kredytowej możesz użyć wskazówek, takich jak AUTOFILL_HINT_CREDIT_CARD_NUMBER
i AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE
.
Aby sprawdzić daty ważności karty kredytowej, wykonaj jedną z tych czynności:
- Jeśli do określania daty ważności używasz jednego widoku danych, użyj
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE
. - Jeśli chcesz używać innego widoku dla każdej części daty ważności, możesz użyć atrybutów
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY
,AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH
iAUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR
w każdym z widoków.
Adres pocztowy
W przypadku pól formularza adresu pocztowego możesz użyć takich podpowiedzi:
- Aby wyświetlić adres w jednym widoku, użyj
AUTOFILL_HINT_POSTAL_ADDRESS
. - Jeśli używasz osobnych widoków do różnych części adresu, możesz skorzystać z tych opcji:
imiona i nazwiska,
Prosząc o imiona i nazwiska osób, możesz skorzystać z następujących wskazówek:
- Aby automatycznie wypełnić imię i nazwisko osoby w pojedynczym widoku, użyj
AUTOFILL_HINT_PERSON_NAME
. - Jeśli korzystasz z osobnych widoków dla różnych części nazwy, możesz zastosować dowolne z tych opcji:
Numery telefonów
W przypadku numerów telefonów możesz użyć:
- Aby poprosić o pełny numer telefonu w jednym widoku, użyj
AUTOFILL_HINT_PHONE_NUMBER
. - Jeśli używasz oddzielnych widoków do różnych części numeru telefonu, możesz użyć jednej z tych opcji:
Hasło jednorazowe
Aby wyświetlić hasło jednorazowe w jednym widoku, możesz użyćAUTOFILL_HINT_SMS_OTP
.
W przypadku wielu widoków, z których każdy odpowiada jednej cyfrze kodu OTP, możesz użyć metody generateSmsOtpHintForCharacterPosition()
do generowania podpowiedzi dotyczących poszczególnych znaków.
Oznaczanie pól jako ważnych dla funkcji autouzupełniania
Poszczególne pola w aplikacji możesz uwzględnić w strukturze widoku na potrzeby autouzupełniania. Domyślnie widoki korzystają z trybu IMPORTANT_FOR_AUTOFILL_AUTO
, który pozwala Androidowi korzystać z heurystyki, aby określić, czy widok jest ważny dla funkcji autouzupełniania.
Są jednak przypadki, w których widok, struktura widoku lub cała aktywność nie jest ważna dla funkcji autouzupełniania:
- Pole
CAPTCHA
w aktywności logowania - Widok, w którym użytkownik tworzy treści, np. edytor tekstu lub arkusza kalkulacyjnego
- wyświetlenia w niektórych aktywnościach w grach, np. w tych, które pokazują rozgrywkę;
Ważność widoku możesz określić za pomocą atrybutu android:importantForAutofill
:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:importantForAutofill="no" />
Wartość importantForAutofill
może być dowolną z tych wartości:
auto
- Pozostaw systemowi Android możliwość korzystania z heurystyki do określania, czy widok jest ważny dla autouzupełniania.
no
- Ten widok nie jest ważny dla autouzupełniania.
noExcludeDescendants
- Ten widok i jego elementy nie są istotne dla funkcji autouzupełniania.
yes
- Ten widok jest ważny dla funkcji autouzupełniania.
yesExcludeDescendants
- Ten widok jest ważny w przypadku autouzupełniania, ale jego elementy podrzędne nie są istotne.
Możesz też użyć metody setImportantForAutofill()
:
Kotlin
val captcha = findViewById<TextView>(R.id.captcha) captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)
Java
TextView captcha = findViewById(R.id.captcha); captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);
Powyższe przykładowe przypadki użycia możesz zadeklarować jako nieistotne dla funkcji autouzupełniania w ten sposób:
- Pole
CAPTCHA
w aktywności logowania: użyj wartościandroid:importantForAutofill="no"
lubIMPORTANT_FOR_AUTOFILL_NO
aby oznaczyć to widok jako nieważny. - Widok, w którym użytkownik tworzy treści: użyj opcji
android:importantForAutofill="noExcludeDescendants"
lubIMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
, aby oznaczyć całą strukturę widoku jako nieistotną. - Widok w niektórych aktywnościach w grach: użyj
android:importantForAutofill="noExcludeDescendants"
lubIMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
, aby oznaczyć całą strukturę widoku jako nieistotną.
Powiązanie danych witryny i aplikacji mobilnej
Usługi autouzupełniania, takie jak autouzupełnianie Google, mogą udostępniać dane logowania użytkownika w przeglądarkach i na urządzeniach z Androidem po powiązaniu aplikacji z witryną. Jeśli użytkownik wybierze tę samą usługę autouzupełniania na obu platformach, zalogowanie się w aplikacji internetowej spowoduje udostępnienie danych logowania do autouzupełniania w momencie logowania się w odpowiedniej aplikacji na Androida.
Aby powiązać aplikację na Androida z witryną, prześlij do niej link do zasobu cyfrowego z relacją delegate_permission/common.get_login_creds
. Następnie zadeklaruj powiązanie w pliku AndroidManifest.xml
aplikacji. Szczegółowe instrukcje dotyczące kojarzenia witryny z aplikacją na Androida znajdziesz w artykule Włączanie automatycznego logowania w aplikacjach i witrynach.
Dokończ przepływ pracy autouzupełniania
W tej sekcji opisaliśmy konkretne scenariusze, w których możesz podjąć działania w celu ulepszenia funkcji autouzupełniania dla użytkowników aplikacji.
Sprawdzanie, czy autouzupełnianie jest włączone
Użytkownicy mogą włączać i wyłączać autouzupełnianie oraz zmieniać usługę autouzupełniania, wybierając Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Asystent wprowadzania > Usługa autouzupełniania. Aplikacja nie może zastąpić ustawień autouzupełniania użytkownika, ale możesz wdrożyć dodatkowe funkcje autouzupełniania w aplikacji lub w określonych widokach, jeśli autouzupełnianie jest dostępne dla użytkownika.
Jeśli na przykład użytkownik ma włączone autouzupełnianie, w menu TextView
będzie wyświetlany wpis autouzupełniania. Aby sprawdzić, czy autouzupełnianie jest włączone dla użytkownika, wywołaj metodę isEnabled()
obiektu AutofillManager
.
Aby proces rejestracji i logowania był zoptymalizowany pod kątem użytkowników, którzy nie korzystają z automatycznego wypełniania formularzy, wprowadź logowanie jednym kliknięciem.
Wymuszanie żądania autouzupełniania
Czasami trzeba wymusić żądanie autouzupełniania w odpowiedzi na działanie użytkownika. Na przykład TextView
oferuje opcję autouzupełniania, gdy użytkownik dotyka i przytrzymuje widok.
Ten przykładowy kod pokazuje, jak wymusić żądanie automatycznego wypełniania:
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); } }
Możesz też użyć metody cancel()
, aby anulować bieżący kontekst autouzupełniania. Może to być przydatne, jeśli masz przycisk, który czyści pola na stronie logowania.
Używaj prawidłowego typu autouzupełniania danych w selektorach
Selektory mogą być przydatne w przypadku funkcji autouzupełniania, ponieważ zapewniają interfejs, który umożliwia użytkownikom zmianę wartości pola przechowującego dane o dacie lub godzinie. Na przykład w formularzu karty kredytowej selektor daty umożliwia użytkownikowi wpisanie lub zmianę daty ważności karty. Aby jednak wyświetlić dane, gdy selektor nie jest widoczny, musisz użyć innego widoku, np. EditText
.
Obiekt EditText
domyślnie oczekuje danych autouzupełniania typu AUTOFILL_TYPE_TEXT
.
Jeśli używasz innego typu danych, utwórz widok niestandardowy, który dziedziczy z EditText
i implementuje metody wymagane do obsługi odpowiedniego typu danych. Jeśli na przykład masz pole daty, zaimplementuj metody z logiką, która prawidłowo obsługuje wartości typu AUTOFILL_TYPE_DATE
.
Gdy określisz typ danych autouzupełniania, usługa autouzupełniania może utworzyć odpowiednią reprezentację danych wyświetlanych w widoku. Więcej informacji znajdziesz w artykule Używanie selektorów z automatycznym wypełnianiem.
Dokończ kontekst autouzupełniania
System autouzupełniania zapisuje dane wprowadzane przez użytkownika, aby można było ich użyć w przyszłości. Po zakończeniu autouzupełniania wyświetla się okno „Zapisz do autouzupełniania?”. Zazwyczaj kontekst autouzupełniania jest usuwany po zakończeniu aktywności. Są jednak sytuacje, w których musisz wyraźnie poinformować framework. Dzieje się tak na przykład, gdy używasz tej samej aktywności, ale różnych fragmentów na ekranie logowania i ekranie treści. W takich sytuacjach możesz jawnie zakończyć kontekst, wywołując funkcję AutofillManager.commit()
.
Obsługa widoków niestandardowych
Widoki niestandardowe mogą określać metadane udostępniane frameworkowi autouzupełniania za pomocą interfejsu AutoFill API. Niektóre widoki działają jako kontenery wirtualnych podrzędnych, na przykład widoki zawierające interfejs renderowany przez OpenGL. Zanim te widoki zaczną działać z ramami automatycznego wypełniania, muszą używać interfejsu API do określania struktury informacji używanych w aplikacji.
Jeśli aplikacja używa widoków niestandardowych, rozważ te scenariusy:
- Widok niestandardowy zawiera standardową strukturę widoku lub domyślną strukturę widoku.
- Widok niestandardowy ma strukturę wirtualną lub strukturę, która jest niedostępna dla platformy autouzupełniania.
Widoki niestandardowe o strukturze widoku standardowego
Widoki niestandardowe mogą definiować metadane, których autouzupełnianie wymaga do działania. Upewnij się, że widok niestandardowy zarządza metadanymi w odpowiednim sposób, aby współpracował z ramówką autouzupełniania. Widok niestandardowy musi wykonywać te działania:
- Obsługa wartości autouzupełniania, którą framework wysyła do aplikacji.
- Podaj typ i wartość autouzupełniania do frameworku.
Po aktywowaniu autouzupełniania platforma autouzupełniania wywołuje w widoku autofill()
i wysyła wartość, której musi użyć Twój widok. Aby określić, jak widok niestandardowy ma obsługiwać wartość autouzupełniania, użyj elementu autofill()
.
Widok musi określać typ i wartość autouzupełniania, zastępując metody getAutofillType()
i getAutofillValue()
.
Autouzupełnianie nie może wypełniać widoku, jeśli użytkownik nie może podać wartości dla widoku w jego bieżącym stanie, np. gdy jest on wyłączony.
W takich przypadkach getAutofillType()
musi zwrócić AUTOFILL_TYPE_NONE
, getAutofillValue()
musi zwrócić null
, a autofill()
nie może nic robić.
Aby prawidłowo korzystać z ramy, musisz wykonać dodatkowe czynności w tych przypadkach:
- Widok niestandardowy można edytować.
- Widok niestandardowy zawiera dane wrażliwe.
Widok niestandardowy można edytować.
Jeśli widok jest edytowalny, poinformuj framework autouzupełniania o zmianach, wywołując funkcję notifyValueChanged()
obiektu AutofillManager
.
Widok niestandardowy zawiera dane wrażliwe
Jeśli widok zawiera informacje umożliwiające identyfikację, takie jak adresy e-mail, numery kart kredytowych i hasła, musi być oznaczony jako poufny.
Widoki, których treści pochodzą z zasobów statycznych, nie zawierają danych wrażliwych, a widoki, których zawartość jest ustalana dynamicznie, mogą zawierać dane wrażliwe. Na przykład etykieta zawierająca tekst Wpisz swoją nazwę użytkownika nie zawiera danych wrażliwych, podczas gdy etykieta zawierająca tekst Cześć, Janie już tak.
System autouzupełniania zakłada, że wszystkie dane są domyślnie wrażliwe. Możesz oznaczać dane, które nie są poufne.
Aby oznaczyć, czy widok zawiera dane wrażliwe, zaimplementuj funkcję onProvideAutofillStructure()
i wywołaj ją w obiekcie ViewStructure
.setDataIsSensitive()
Poniższy przykład kodu pokazuje, jak oznaczyć dane w strukturze widoku jako niepoufne:
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); }
Jeśli widok akceptuje tylko wstępnie zdefiniowane wartości, możesz użyć metody setAutofillOptions()
, aby ustawić opcje, które można wykorzystać do automatycznego wypełniania widoku. W szczególności widoki, których typ autouzupełniania to
AUTOFILL_TYPE_LIST
, muszą używać tej metody, ponieważ usługa autouzupełniania może lepiej działać, jeśli zna opcje dostępne do wypełnienia widoku.
Podobnie jest w przypadku widoków, które korzystają z przejściówki, np. Spinner
. Na przykład spinner, który dynamicznie generuje lata na podstawie bieżącego roku, aby użyć ich w polach wygaśnięcia karty kredytowej, może implementować metodę getAutofillOptions()
interfejsu Adapter
, aby podać listę lat.
Widoki, które używają parametru ArrayAdapter
, mogą też zawierać listy wartości. ArrayAdapter
automatycznie ustawia opcje autouzupełniania w przypadku zasobów statycznych.
Jeśli podajesz wartości dynamicznie, zastąp parametr getAutofillOptions()
.
Widoki niestandardowe z wirtualną strukturą
Platforma autouzupełniania wymaga struktury widoku, aby móc edytować i zapisywać informacje w interfejsie aplikacji. Struktura widoku jest niedostępna dla frameworka w tych sytuacjach:
- Do renderowania UI aplikacja wykorzystuje silnik renderowania niskiego poziomu, taki jak OpenGL.
- Aplikacja używa instancji
Canvas
do wyświetlania interfejsu.
W takich przypadkach możesz określić strukturę widoku, wdrażając onProvideAutofillVirtualStructure()
i wykonując te czynności:
- Zwiększ liczbę elementów podrzędnych w strukturze widoku, wywołując funkcję
addChildCount()
. - Dodaj dziecko, dzwoniąc na numer
newChild()
. - Aby ustawić identyfikator automatycznego wypełniania dla dziecka, wywołaj funkcję
setAutofillId()
. - Ustaw odpowiednie właściwości, takie jak wartość i typ autouzupełniania.
- Jeśli dane wirtualnego dziecka są wrażliwe, prześlij
true
dosetDataIsSensitive()
; w przeciwnym razie prześlijfalse
.
Ten fragment kodu pokazuje, jak utworzyć nowy element podrzędny w strukturze wirtualnej:
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); }
Gdy elementy wirtualnej struktury ulegną zmianie, poinformuj o tym framework, wykonując te czynności:
- Jeśli punkt skupienia wewnątrz elementów podrzędnych ulegnie zmianie, wywołaj funkcję
notifyViewEntered()
inotifyViewExited()
na obiekcieAutofillManager
. - Jeśli wartość elementu podrzędnego ulegnie zmianie, wywołaj funkcję
notifyValueChanged()
obiektuAutofillManager
. - Jeśli hierarchia widoku nie jest już dostępna, ponieważ użytkownik ukończył krok w przepływie pracy, np. zalogował się za pomocą formularza logowania, wywołaj funkcję
commit()
obiektuAutofillManager
. - Jeśli hierarchia widoków jest nieprawidłowa, ponieważ użytkownik anulował krok w przepływie pracy, na przykład kliknięcie przycisku otwierającego formularz logowania, wywołaj
cancel()
w obiekcieAutofillManager
.
Używanie wywołań zwrotnych w przypadku zdarzeń autouzupełniania
Jeśli aplikacja udostępnia własne widoki autouzupełniania, musisz użyć mechanizmu, który powoduje w niej włączenie lub wyłączenie tych widoków w reakcji na zmiany w interfejsie autouzupełniania. Platforma autouzupełniania udostępnia ten mechanizm w postaci AutofillCallback
.
Ta klasa udostępnia metodę onAutofillEvent(View, int)
, którą aplikacja wywołuje po zmianie stanu autouzupełniania powiązanego z widokiem.
Istnieje też przeciążona wersja tej metody, która zawiera parametr childId
, którego Twoja aplikacja może używać w przypadku wyświetleń wirtualnych. Dostępne stany są zdefiniowane jako stałe w połączeniu zwrotnym.
Możesz zarejestrować wywołanie zwrotne za pomocą metody registerCallback()
klasy AutofillManager
. Poniższy przykładowy kod pokazuje, jak zadeklarować wywołanie zwrotne dla zdarzeń autouzupełniania:
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; } } });
Gdy nadejdzie czas na usunięcie wywołania zwrotnego, użyj metody unregisterCallback()
.
Dostosowywanie wyróżnionego obiektu do wypełniania
Gdy widok danych jest uzupełniony automatycznie, platforma renderuje w nim obiekt Drawable
, aby wskazać, że jego zawartość jest wypełniana automatycznie. Domyślnie ten element jest wypełnionym prostokątem w przezroczystym kolorze, który jest nieco ciemniejszy niż kolor motywu używany do rysowania tła. Nie musisz tego zmieniać, ale możesz go dostosować, zastępując element android:autofilledHighlight
motywu używanego przez aplikację lub działanie, jak w tym przykładzie:
<resources>
<style name="MyAutofilledHighlight" parent="...">
<item name="android:autofilledHighlight">@drawable/my_drawable</item>
</style>
</resources>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4DFF0000" />
</shape>
<application ...
android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
android:theme="@style/MyAutofilledHighlight">
Uwierzytelnij na potrzeby autouzupełniania
Usługa autouzupełniania może wymagać uwierzytelnienia użytkownika, zanim będzie mogła wypełnić pola w aplikacji. W takim przypadku system Android uruchamia aktywność uwierzytelniania usługi jako część stosu aktywności.
Nie musisz aktualizować aplikacji, aby obsługiwała uwierzytelnianie, ponieważ uwierzytelnianie odbywa się w ramach usługi. Musisz jednak zadbać o to, by struktura widoku aktywności została zachowywana po ponownym uruchomieniu, np. po utworzeniu struktury widoku w onCreate()
, a nie w onStart()
czy onResume()
.
Aby sprawdzić, jak aplikacja zachowuje się, gdy usługa autouzupełniania wymaga uwierzytelnienia, użyj HeuristicsService z przykładowej aplikacji AutofillFramework i skonfiguruj ją tak, aby wymagała uwierzytelniania odpowiedzi autouzupełniania. Aby emulować ten problem, możesz też użyć przykładu BadViewStructureCreationSignInActivity.
Przypisywanie identyfikatorów autouzupełniania do odzyskanych wyświetleń
Kontenery, które odświeżają widoki, takie jak klasa RecyclerView
, są przydatne w aplikacjach, które muszą wyświetlać przewijane listy elementów na podstawie dużych zbiorów danych. Podczas przewijania kontenera system ponownie wykorzystuje widoki w układzie, ale widoki zawierają nowe treści.
Jeśli początkowe treści w ponowtórzonym widoku są wypełnione, usługa autouzupełniania zachowuje logiczne znaczenie widoków za pomocą ich identyfikatorów autouzupełniania. Problem pojawia się, gdy system ponownie używa widoków w układzie, a ich identyfikatory logiczne pozostają takie same, co powoduje, że z identyfikatorem autouzupełniania powiązane są niewłaściwe dane użytkownika.
Aby rozwiązać ten problem na urządzeniach z Androidem 9 (poziom interfejsu API 28) lub nowszym, bezpośrednio zarządzaj identyfikatorem autouzupełniania widoków, których używa RecyclerView
, korzystając z tych metod:
- Metoda
getNextAutofillId()
otrzymuje nowy identyfikator autouzupełniania, który jest unikalny dla danej aktywności. - Metoda
setAutofillId()
ustawia w działaniu unikalny, logiczny identyfikator automatycznego wypełniania tego widoku.
Rozwiązywanie znanych problemów
W tej sekcji znajdziesz obejścia znanych problemów w ramach systemu autouzupełniania.
Autouzupełnianie powoduje awarię aplikacji na Androidzie 8.0 i 8.1
W Androidzie 8.0 (poziom interfejsu API 26) i 8.1 (poziom interfejsu API 27) autouzupełnianie może w niektórych sytuacjach spowodować awarię aplikacji. Aby uniknąć potencjalnych problemów, otaguj widoki, które nie są wypełniane automatycznie, wartością importantForAutofill=no
. Możesz też oznaczyć cały trening tagiem importantForAutofill=noExcludeDescendants
.
Dialogi o zmienionym rozmiarze nie są uwzględniane w autouzupełnianiu
W Androidzie 8.1 (poziom interfejsu API 27) i starszych, jeśli rozmiar widoku w dialogu zostanie zmieniony po wyświetleniu, widok nie jest uwzględniany w autouzupełnianiu. Te widoki nie są uwzględniane w obiekcie AssistStructure
, który system Android wysyła do usługi autouzupełniania. W związku z tym usługa nie może wypełniać widoków.
Aby obejść ten problem, zastąp atrybut token
parametrów okna dialogowego atrybutem token
aktywności, która tworzy okno dialogowe. Po sprawdzeniu, czy autouzupełnianie jest włączone, zapisz parametry okna w metodzie onWindowAttributesChanged()
klasy, która dziedziczy z Dialog
. Następnie zastąp właściwość token
zapisanych parametrów właściwością token
aktywności nadrzędnej w metodzie onAttachedToWindow()
.
Fragment kodu poniżej pokazuje klasę, w której zastosowano to obejście:
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(); } }
Aby uniknąć niepotrzebnych operacji, w tym fragmencie kodu pokazano, jak sprawdzić, czy automatyczne wypełnianie jest obsługiwane na urządzeniu i włączone dla bieżącego użytkownika oraz czy to obejście jest wymagane:
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(); } }
Testowanie aplikacji za pomocą autouzupełniania
Po zoptymalizowaniu aplikacji pod kątem współpracy z usługami autouzupełniania sprawdź, czy działa ona prawidłowo z tymi usługami.
Aby przetestować aplikację, użyj emulatora lub fizycznego urządzenia z Androidem 8.0 (poziom interfejsu API 26) lub nowszym. Więcej informacji o tworzeniu emulatora znajdziesz w artykule Tworzenie urządzeń wirtualnych i zarządzanie nimi.
Instalowanie usługi autouzupełniania
Zanim przetestujesz aplikację z autouzupełnianiem, musisz zainstalować inną aplikację, która udostępnia usługi autouzupełniania. Do tego celu możesz użyć aplikacji innej firmy, ale łatwiej jest skorzystać z przykładowej usługi autouzupełniania, dzięki czemu nie musisz rejestrować się w usługach innych firm.
Aby przetestować aplikację z usługami autouzupełniania, możesz użyć przykładowego frameworku autouzupełniania na Androida w języku Java. Przykładowa aplikacja udostępnia usługę autouzupełniania i klasy Activity
klienta, których możesz użyć do przetestowania przepływu pracy przed użyciem go w swojej aplikacji. Ta strona odwołuje się do przykładowej aplikacji android-AutofillFramework.
Po zainstalowaniu aplikacji włącz usługę autouzupełniania w ustawieniach systemu emulatora. Aby to zrobić, kliknij Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Asystent wprowadzania > Usługa autouzupełniania.
Analiza wymagań dotyczących danych
Aby przetestować aplikację za pomocą usługi autouzupełniania, usługa musi mieć dane, których może użyć do wypełnienia aplikacji. Usługa musi też wiedzieć, jakiego typu danych oczekuje się w widokach aplikacji. Jeśli na przykład aplikacja ma widok, który wymaga nazwy użytkownika, usługa musi mieć zbiór danych zawierający nazwę użytkownika i jakiś mechanizm, który pozwoli jej rozpoznać, że widok oczekuje takich danych.
Poinformuj usługę, jakiego typu dane są oczekiwane w widokach, ustawiając atrybut android:autofillHints
. Niektóre usługi używają zaawansowanych metod heurystycznych do określania typu danych, ale inne, takie jak przykładowa aplikacja, polegają na tym, że deweloper podaje te informacje. Aplikacja będzie lepiej współpracować z usługami autouzupełniania, jeśli w widokach istotnych dla autouzupełniania ustawisz atrybut android:autofillHints
.
Przeprowadź test
Po przeanalizowaniu wymagań dotyczących danych możesz uruchomić test, który obejmuje zapisanie danych testowych w usłudze autouzupełniania i aktywowanie autouzupełniania w aplikacji.
Zapisywanie danych w usłudze
Aby zapisać dane w obecnie aktywnej usłudze autouzupełniania:
- Otwórz aplikację zawierającą widok, który wymaga typu danych, których chcesz użyć podczas testu. Przykładowa aplikacja android-AutofillFramework udostępnia interfejs użytkownika z widokami, które wymagają kilku typów danych, takich jak numery kart kredytowych i nazwy użytkowników.
- Kliknij widok zawierający potrzebny typ danych.
- Wpisz wartość w widoku.
- Kliknij przycisk potwierdzenia, np. Zaloguj się lub Prześlij. Zwykle formularz musisz przesłać, zanim usługa zapisze dane.
- Sprawdź prośbę o uprawnienia w oknie systemowym. W oknie systemowym wyświetla się nazwa usługi, która jest obecnie aktywna, i pytanie, czy chcesz jej użyć w teście. Jeśli chcesz skorzystać z usługi, kliknij Zapisz.
Jeśli Android nie wyświetla okna uprawnień lub usługa nie jest tą, której chcesz używać w teście, sprawdź w ustawieniach systemu, czy jest obecnie aktywna.
Aktywowanie autouzupełniania w aplikacji
Aby aktywować automatyczne wypełnianie w aplikacji:
- Otwórz aplikację i otwórz aktywność, która zawiera widoki, które chcesz przetestować.
- Kliknij widok, który chcesz wypełnić.
- System wyświetla interfejs autouzupełniania, który zawiera zbiory danych, które mogą wypełnić widok, jak pokazano na rysunku 1.
- Kliknij zbiór danych zawierający dane, których chcesz użyć. Widok ten wyświetla dane wcześniej zapisane w usłudze.
Jeśli Android nie wyświetla interfejsu autouzupełniania, wypróbuj te sposoby rozwiązania problemu:
- Sprawdź, czy widoki w aplikacji używają prawidłowej wartości w atributach
android:autofillHints
. Listę możliwych wartości tego atrybutu znajdziesz w klasieView
w konstantach z przedrostkiemAUTOFILL_HINT
. - Sprawdź, czy atrybut
android:importantForAutofill
ma ustawioną wartość inną niżno
w widoku, który wymaga wypełnienia, lub inną niżno
w widoku lub w jednym z jego elementów nadrzędnych.noExcludeDescendants