Aplikacje, które korzystają ze standardowych widoków, działają z platformą autouzupełniania bez konieczności specjalnej konfiguracji. Możesz też zoptymalizować sposób, w jaki aplikacja współpracuje z tym frameworkiem.
Konfigurowanie środowiska autouzupełniania
W tej sekcji opisano, jak skonfigurować podstawową funkcję autouzupełniania w aplikacji.
Konfigurowanie usługi autouzupełniania
Aby aplikacja mogła korzystać z platformy autouzupełniania, na urządzeniu musi być skonfigurowana usługa autouzupełniania. Większość telefonów i tabletów z Androidem 8.0 (API na poziomie 26) lub nowszym jest dostarczana z usługą autouzupełniania. Podczas testowania aplikacji zalecamy jednak korzystanie z usługi testowej, np. usługi autouzupełniania w przykładowym frameworku autouzupełniania na Androidzie. 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 ją, wybierając Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Pomoc przy wpisywaniu > Usługa autouzupełniania.
Więcej informacji o konfigurowaniu emulatora do testowania autouzupełniania znajdziesz w artykule Testowanie aplikacji za pomocą autouzupełniania.
Podawanie wskazówek dotyczących autouzupełniania
Usługa autouzupełniania określa typ każdego widoku za pomocą heurystyki. Jeśli jednak Twoja aplikacja korzysta z tych heurystyk, zachowanie autouzupełniania może się nieoczekiwanie zmienić podczas aktualizacji aplikacji. Aby usługa autouzupełniania prawidłowo identyfikowała formaty aplikacji, podaj wskazówki dotyczące autouzupełniania.
Wskazówki dotyczące autouzupełniania możesz ustawić za pomocą atrybutu
android:autofillHints
. W tym przykładzie ustawiamy wskazówkę "password"
w elemencie EditText
:
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:autofillHints="password" />
Wskazówki możesz też ustawić programowo za pomocą metody setAutofillHints()
, jak pokazano 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 podpowiedzi
Platforma autouzupełniania nie weryfikuje wskazówek. Są one przekazywane do usługi autouzupełniania bez zmian i weryfikacji. Możesz użyć dowolnej wartości, ale klasy View
i AndroidX HintConstants
zawierają listy oficjalnie obsługiwanych stałych podpowiedzi.
Używając kombinacji tych stałych, możesz tworzyć układy dla typowych scenariuszy autouzupełniania:
Dane logowania
W formularzu logowania możesz umieścić wskazówki dotyczące danych logowania do konta, np. AUTOFILL_HINT_USERNAME
i AUTOFILL_HINT_PASSWORD
.
Do tworzenia nowego konta lub 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 prośby o informacje o karcie kredytowej możesz używać wskazówek, takich jak
AUTOFILL_HINT_CREDIT_CARD_NUMBER
i
AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE
.
W przypadku dat ważności kart kredytowych wykonaj jedną z tych czynności:
- Jeśli używasz pojedynczego widoku daty ważności, użyj symbolu
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE
. - Jeśli dla każdej części daty ważności używasz innego widoku, możesz użyć
AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY
,AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH
, iAUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR
dla każdego widoku.
Adres pocztowy
W przypadku pól formularza adresu pocztowego możesz użyć takich wskazówek:
- W przypadku adresu w widoku pojedynczym użyj
AUTOFILL_HINT_POSTAL_ADDRESS
. - Jeśli używasz osobnych widoków dla różnych części adresu, możesz użyć tych elementów:
Imiona i nazwiska
Gdy prosisz o podanie imion, możesz użyć takich wskazówek:
- Aby autouzupełnić pełne imię i nazwisko osoby w jednym widoku, użyj
AUTOFILL_HINT_PERSON_NAME
. - Jeśli używasz osobnych widoków danych dla różnych części nazwy, możesz użyć dowolnego z tych elementów:
Numery telefonów
W przypadku numerów telefonu możesz używać tych znaków:
- Jeśli chcesz poprosić o pełny numer telefonu w jednym widoku, użyj adresu
AUTOFILL_HINT_PHONE_NUMBER
. - Jeśli używasz osobnych widoków dla różnych części numeru telefonu, możesz użyć dowolnego z tych elementów:
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 jest mapowany na jedną cyfrę kodu OTP, możesz użyć metody generateSmsOtpHintForCharacterPosition()
, aby wygenerować podpowiedzi dla poszczególnych znaków.
Łączenie danych witryny i aplikacji mobilnej
Usługi autouzupełniania, takie jak autouzupełnianie Google, mogą udostępniać dane logowania użytkownika między przeglądarkami i urządzeniami z Androidem po powiązaniu aplikacji i witryny. 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 podczas logowania się w odpowiedniej aplikacji na Androida.
Aby powiązać aplikację na Androida z witryną, umieść w niej Digital Asset Link z relacją delegate_permission/common.get_login_creds
. Następnie zadeklaruj powiązanie w pliku AndroidManifest.xml
aplikacji. Szczegółowe instrukcje dotyczące powiązania 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 opisujemy konkretne scenariusze, w których możesz podjąć działania, aby ulepszyć funkcję autouzupełniania dla użytkowników Twojej aplikacji.
Sprawdzanie, czy autouzupełnianie jest włączone
Użytkownicy mogą włączać i wyłączać autouzupełnianie oraz zmieniać usługę autouzupełniania, otwierając Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Pomoc przy wpisywaniu > Usługa autouzupełniania. Aplikacja nie może zastępować ustawień autouzupełniania użytkownika, ale jeśli autouzupełnianie jest dostępne dla użytkownika, możesz zaimplementować dodatkowe funkcje autouzupełniania w aplikacji lub w określonych widokach aplikacji.
Na przykład TextView
pokazuje wpis autouzupełniania w menu przepełnienia, jeśli autouzupełnianie jest włączone dla użytkownika. Aby sprawdzić, czy autouzupełnianie jest włączone dla użytkownika, wywołaj metodę isEnabled()
obiektu AutofillManager
.
Aby mieć pewność, że proces rejestracji i logowania jest zoptymalizowany pod kątem użytkowników, którzy nie korzystają z autouzupełniania, wdróż logowanie jednym kliknięciem.
Wymuszanie żądania autouzupełniania
Czasami musisz wymusić wysłanie żądania autouzupełniania w odpowiedzi na działanie użytkownika. Na przykład TextView
oferuje element menu autouzupełniania, gdy użytkownik dotknie widoku i przytrzyma go.
Poniższy przykład kodu pokazuje, jak wymusić żądanie autouzupeł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żywanie prawidłowego typu autouzupełniania w przypadku danych w kontrolkach selektora
Selektory mogą być przydatne w przypadku autouzupełniania, ponieważ udostępniają interfejs, który umożliwia użytkownikom zmianę wartości pola przechowującego dane daty lub godziny. Na przykład w formularzu karty kredytowej selektor daty umożliwia użytkownikom wpisanie lub zmianę daty ważności karty kredytowej. Gdy selektor nie jest widoczny, musisz jednak użyć innego widoku, np. EditText
, aby wyświetlić dane.
Obiekt EditText
natywnie oczekuje danych autouzupełniania typu AUTOFILL_TYPE_TEXT
.
Jeśli używasz innego typu danych, utwórz widok niestandardowy, który dziedziczy po 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 Korzystanie z selektorów z autouzupełnianiem.
Dokończ kontekst autouzupełniania
Platforma autouzupełniania zapisuje dane wprowadzane przez użytkownika, aby można było z nich korzystać w przyszłości. Po zakończeniu kontekstu autouzupełniania wyświetla okno „Zapisać do autouzupełniania?”. Zazwyczaj kontekst autouzupełniania kończy się wraz z zakończeniem działania. W niektórych sytuacjach musisz jednak wyraźnie powiadomić platformę, np. jeśli używasz tego samego działania, ale różnych fragmentów na ekranach logowania i 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 platformie autouzupełniania za pomocą interfejsu Autofill API. Niektóre widoki działają jako kontener wirtualnych elementów podrzędnych, np. widoki zawierające interfejs renderowany za pomocą OpenGL. Zanim te widoki będą mogły współpracować z platformą autouzupełniania, muszą używać interfejsu API do określania struktury informacji używanych w aplikacji.
Jeśli Twoja aplikacja korzysta z widoków niestandardowych, weź pod uwagę te scenariusze:
- Widok niestandardowy ma standardową strukturę widoku lub domyślną strukturę widoku.
- Widok niestandardowy ma strukturę wirtualną, czyli strukturę widoku, która nie jest dostępna dla platformy autouzupełniania.
Widoki niestandardowe o strukturze widoku standardowego
Widoki niestandardowe mogą definiować metadane, które są wymagane do działania autouzupełniania. Upewnij się, że widok niestandardowy odpowiednio zarządza metadanymi, aby współpracować z platformą autouzupełniania. Niestandardowy widok musi wykonać te czynności:
- Obsługuj wartość autouzupełniania, którą platforma wysyła do aplikacji.
- Przekaż do platformy typ i wartość autouzupełniania.
Gdy zostanie uruchomione automatyczne wypełnianie, framework automatycznego wypełniania wywołuje autofill()
w widoku i wysyła wartość, której musi użyć widok. Zaimplementuj autofill()
, aby określić, jak niestandardowy widok obsługuje wartość autouzupełniania.
Widok musi określać typ i wartość autouzupełniania przez zastąpienie odpowiednio metod
getAutofillType()
i
getAutofillValue()
.
Autouzupełnianie nie może też wypełniać widoku, jeśli użytkownik nie może podać wartości dla widoku w jego bieżącym stanie, np. jeśli widok jest wyłączony.
W takich przypadkach funkcja getAutofillType()
musi zwrócić wartość AUTOFILL_TYPE_NONE
, funkcja getAutofillValue()
musi zwrócić wartość null
, a funkcja autofill()
nie musi nic robić.
W tych przypadkach wymagane są dodatkowe czynności, aby prawidłowo korzystać z ram:
- Widok niestandardowy można edytować.
- Widok niestandardowy zawiera dane wrażliwe.
Widok niestandardowy można edytować
Jeśli widok można edytować, powiadom platformę autouzupełniania o zmianach, wywołując
notifyValueChanged()
na obiekcie 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 zawierający dane wrażliwe.
Ogólnie rzecz biorąc, widoki, których treść pochodzi ze statycznych zasobów, nie zawierają danych wrażliwych, natomiast widoki, których treść jest ustawiana dynamicznie, mogą zawierać dane wrażliwe. Na przykład etykieta zawierająca tekst wpisz nazwę użytkownika nie zawiera danych wrażliwych, a etykieta zawierająca tekst Cześć, Janie już tak.
Framework autouzupełniania zakłada, że wszystkie dane są domyślnie wrażliwe. Możesz oznaczyć dane, które nie są poufne.
Aby oznaczyć, czy widok zawiera dane wrażliwe, zaimplementuj
onProvideAutofillStructure()
i wywołaj
setDataIsSensitive()
na obiekcie ViewStructure
.
Poniższy przykład kodu pokazuje, jak oznaczyć dane w strukturze widoku jako nieobjęte ochroną:
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()
do ustawienia opcji, które można wykorzystać do autouzupeł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 działać lepiej, jeśli zna opcje dostępne do wypełnienia widoku.
Podobna sytuacja występuje w przypadku widoków, które korzystają z adaptera, np. Spinner
. Na przykład selektor, który dynamicznie tworzy lata na podstawie bieżącego roku, aby używać ich w polach daty ważności karty kredytowej, może implementować metodę getAutofillOptions()
interfejsu Adapter
, aby udostępniać listę lat.
Widoki, które korzystają z 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 ze strukturą wirtualną
Aby edytować i zapisywać informacje w interfejsie aplikacji, platforma autouzupełniania wymaga struktury widoku. Struktura widoku jest niedostępna dla platformy w tych sytuacjach:
- Aplikacja używa silnika renderowania niskiego poziomu, np. OpenGL, do renderowania interfejsu.
- Aplikacja używa instancji
Canvas
do rysowania interfejsu.
W takich przypadkach możesz określić strukturę widoku, implementując
onProvideAutofillVirtualStructure()
i wykonując te czynności:
- Zwiększ liczbę elementów podrzędnych w strukturze widoku, wywołując metodę
addChildCount()
. - Dodaj dziecko, dzwoniąc
newChild()
. - Ustaw identyfikator autouzupełniania dla elementu podrzędnego, wywołując funkcję
setAutofillId()
. - Ustaw odpowiednie właściwości, takie jak wartość i typ automatycznego wypełniania.
- Jeśli dane w wirtualnym profilu dziecka są wrażliwe, przekaż wartość
true
dosetDataIsSensitive()
; w przeciwnym razie przekaż wartośćfalse
.
Poniższy fragment kodu pokazuje, jak utworzyć nowe dziecko 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 w strukturze wirtualnej ulegną zmianie, powiadom o tym platformę, wykonując te czynności:
- Jeśli fokus w elementach podrzędnych się zmieni, wywołaj
notifyViewEntered()
inotifyViewExited()
na obiekcieAutofillManager
. - Jeśli wartość elementu podrzędnego ulegnie zmianie, wywołaj funkcję
notifyValueChanged()
na obiekcieAutofillManager
. - Jeśli hierarchia widoków jest już niedostępna, ponieważ użytkownik wykonał krok w procesie, np. zalogował się za pomocą formularza logowania, wywołaj metodę
commit()
na obiekcieAutofillManager
. - Jeśli hierarchia widoków jest nieprawidłowa, ponieważ użytkownik anulował krok w procesie, np. kliknął przycisk, który czyści formularz logowania, wywołaj metodę
cancel()
na obiekcieAutofillManager
.
Używanie wywołań zwrotnych w przypadku zdarzeń autouzupełniania
Jeśli Twoja aplikacja udostępnia własne widoki autouzupełniania, potrzebujesz mechanizmu, który informuje aplikację o włączaniu lub wyłączaniu widoków w odpowiedzi na zmiany w funkcji autouzupełniania interfejsu. 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 aplikacja może używać w przypadku wirtualnych wyświetleń. Dostępne stany są zdefiniowane jako stałe w wywołaniu zwrotnym.
Możesz zarejestrować wywołanie zwrotne za pomocą metody
registerCallback()
klasy AutofillManager
. Poniższy przykład kodu 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 podświetlonego elementu rysowalnego autouzupełniania
Gdy widok zostanie wypełniony automatycznie, platforma renderuje element Drawable
nad widokiem, aby wskazać, że jego zawartość została wypełniona automatycznie. Domyślnie jest to prostokąt wypełniony jednolitym, półprzezroczystym kolorem, który jest nieco ciemniejszy niż kolor motywu używany do rysowania tła. Nie musisz zmieniać elementu rysowalnego, ale możesz go dostosować, zastępując element android:autofilledHighlight
motywu używanego przez aplikację lub aktywność, jak pokazano w tym przykładzie:
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">
Uwierzytelnianie na potrzeby autouzupełniania
Usługa autouzupełniania może wymagać od użytkownika uwierzytelnienia, 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 aplikacji.
Nie musisz aktualizować aplikacji, aby obsługiwała uwierzytelnianie, ponieważ odbywa się ono w ramach usługi. Musisz jednak zadbać o to, aby struktura widoku aktywności została zachowana po jej ponownym uruchomieniu, np. tworząc strukturę widoku w onCreate()
, a nie w onStart()
ani onResume()
.
Możesz sprawdzić, jak aplikacja zachowuje się, gdy usługa autouzupełniania wymaga uwierzytelniania, korzystając z HeuristicsService z przykładowej aplikacji AutofillFramework i konfigurując ją tak, aby wymagała uwierzytelniania odpowiedzi na wypełnienie. Aby zasymulować ten problem, możesz też użyć przykładowego kodu BadViewStructureCreationSignInActivity.
Przypisywanie identyfikatorów autouzupełniania do widoków z odzysku
Kontenery, które ponownie wykorzystują widoki, np. klasa RecyclerView
, są przydatne w przypadku aplikacji, 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 zawierają one nowe treści.
Jeśli początkowa zawartość widoku z odzysku zostanie wypełniona, usługa autouzupełniania zachowa logiczne znaczenie widoków za pomocą ich identyfikatorów autouzupełniania. Problem pojawia się, gdy system ponownie wykorzystuje widoki w układzie. Ich identyfikatory logiczne pozostają takie same, co powoduje, że z identyfikatorem autouzupełniania są powiązane nieprawidłowe dane użytkownika.
Aby rozwiązać ten problem na urządzeniach z Androidem 9 (poziom interfejsu API 28) lub nowszym,RecyclerView
wyraźnie zarządzaj identyfikatorem autouzupełniania widoków używanych przezRecyclerView
za pomocą tych metod:
- Metoda
getNextAutofillId()
pobiera nowy identyfikator autouzupełniania, który jest unikalny dla aktywności. - Metoda
setAutofillId()
ustawia unikalny, logiczny identyfikator autouzupełniania tego widoku w aktywności.
Rozwiązywanie znanych problemów
W tej sekcji znajdziesz obejścia znanych problemów w ramach automatycznego wypełniania.
Autouzupełnianie powoduje awarie aplikacji na Androidzie 8.0 i 8.1
W Androidzie 8.0 (interfejs API na poziomie 26) i 8.1 (interfejs API na poziomie 27) autouzupełnianie może w pewnych sytuacjach powodować awarię aplikacji. Aby uniknąć potencjalnych problemów, oznacz wszystkie wyświetlenia, które nie są wypełniane automatycznie, symbolem importantForAutofill=no
. Możesz też oznaczyć całą aktywność tagiem importantForAutofill=noExcludeDescendants
.
Zmienione okna nie są uwzględniane w autouzupełnianiu
W Androidzie 8.1 (poziom interfejsu API 27) i starszych wersjach, jeśli rozmiar widoku w oknie zostanie zmieniony po jego wyświetleniu, nie będzie on brany pod uwagę podczas autouzupełniania. 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łnić widoków.
Aby obejść ten problem, zastąp właściwość token
parametrów okna dialogowego właściwością 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 po Dialog
. Następnie zastąp właściwość token
zapisanych parametrów właściwością token
aktywności nadrzędnej w metodzie onAttachedToWindow()
.
Poniższy fragment kodu pokazuje klasę, która implementuje 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, poniższy fragment kodu pokazuje, jak sprawdzić, czy na urządzeniu jest obsługiwane autouzupełnianie i czy jest ono 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 usług autouzupełniania sprawdź, czy działa ona zgodnie z oczekiwaniami.
Do testowania aplikacji używaj emulatora lub urządzenia fizycznego z Androidem 8.0 (API na poziomie 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ę za pomocą autouzupełniania, musisz zainstalować inną aplikację, która udostępnia usługi autouzupełniania. W tym celu możesz użyć aplikacji innej firmy, ale łatwiej jest skorzystać z przykładowej usługi autouzupełniania, aby nie musieć rejestrować się w usługach innych firm.
Aby przetestować aplikację z usługami autouzupełniania, możesz użyć przykładowego kodu platformy autouzupełniania na Androida w Javie. Przykładowa aplikacja udostępnia usługę autouzupełniania i klasy klienta Activity
, 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. W tym celu otwórz Ustawienia > System > Języki i metody wprowadzania > Zaawansowane > Pomoc przy wpisywaniu > Usługa autouzupełniania.
Analizowanie 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. Musi też wiedzieć, jakiego rodzaju dane są oczekiwane w widokach aplikacji. Jeśli na przykład aplikacja ma widok, w którym oczekiwana jest nazwa użytkownika, usługa musi mieć zbiór danych zawierający nazwę użytkownika i mechanizm, który informuje, że w widoku oczekiwane są takie dane.
Określ typ danych, które mają być widoczne w widokach, ustawiając atrybut android:autofillHints
. Niektóre usługi używają zaawansowanych heurystyk
do określania typu danych, ale inne, np. aplikacja przykładowa, polegają na tym, że
deweloper podaje te informacje. Aplikacja lepiej współpracuje 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 przeprowadzić test, który obejmuje zapisywanie danych testowych w usłudze autouzupełniania i wywoływanie autouzupełniania w aplikacji.
Zapisywanie danych w usłudze
Aby zapisać dane w usłudze autouzupełniania, która jest obecnie aktywna:
- Otwórz aplikację zawierającą widok, który oczekuje typu danych, jakiego chcesz użyć podczas testu. Przykładowa aplikacja android-AutofillFramework udostępnia interfejs z widokami, które oczekują kilku typów danych, takich jak numery kart kredytowych i nazwy użytkowników.
- Kliknij widok zawierający typ danych, których potrzebujesz.
- Wpisz wartość w widoku.
- Kliknij przycisk potwierdzenia, np. Zaloguj się lub Prześlij. Zwykle musisz przesłać formularz, zanim usługa zapisze dane.
- Sprawdź prośbę o uprawnienia w oknie systemowym. W oknie dialogowym systemu wyświetli się nazwa usługi, która jest obecnie aktywna, oraz pytanie, czy chcesz użyć tej usługi w teście. Jeśli chcesz korzystać z tej usługi, kliknij Zapisz.
Jeśli Android nie wyświetla okna uprawnień lub jeśli usługa nie jest tą, której chcesz użyć w teście, sprawdź, czy jest ona obecnie aktywna w ustawieniach systemu.
Wywoływanie autouzupełniania w aplikacji
Aby wywołać automatyczne wypełnianie w aplikacji:
- Otwórz aplikację i przejdź do aktywności, w której chcesz przetestować widoki.
- 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 wyświetla dane przechowywane wcześniej w usłudze.
Jeśli Android nie wyświetla interfejsu autouzupełniania, możesz wypróbować te rozwiązania:
- Sprawdź, czy widoki w aplikacji używają prawidłowej wartości atrybutu
android:autofillHints
. Listę możliwych wartości atrybutu znajdziesz w stałych poprzedzonych symbolemAUTOFILL_HINT
w klasieView
. - Sprawdź, czy atrybut
android:importantForAutofill
ma ustawioną wartość inną niżno
w widoku, który wymaga wypełnienia, lub wartość inną niżnoExcludeDescendants
w widoku lub jednym z jego elementów nadrzędnych.