Hoe Android O's Autofill Framework te gebruiken

Automatisch invullen van formulieren, vaak afgekort tot alleen automatisch aanvullen, is een functie die browsers al jaren ondersteunen. De meesten van ons gebruiken het de hele tijd. Ik vind het voor een deel onmisbaar tijdens taken zoals het invullen van een registratieformulier of het afronden van een afrekenproces.

De nieuwste versie van Android, Android O, biedt vergelijkbare functionaliteit als Android-apps. Met andere woorden, Android kan nu gebruikers helpen bij het invullen van formulieren die horen bij alle apps die ze op hun apparaten hebben geïnstalleerd. Dit was een langverwachte functie omdat typen met een virtueel toetsenbord op een klein scherm nogal een gedoe is.

Als app-ontwikkelaar kunt u het nieuwe Autofill Framework gebruiken om uw eigen aangepaste autofill-service te maken, een service die beslist hoe de invoervelden van een app moeten worden ingevuld. In deze zelfstudie laat ik je zien hoe.

voorwaarden

Als je deze zelfstudie wilt kunnen volgen, heb je het volgende nodig:

  • Android Studio 2.4 Voorbeeld 7 of hooger
  • Een emulator of apparaat met Android O of hoger

1. Maak een nieuw project

Start Android Studio en maak een nieuw project met een lege activiteit. Je moet natuurlijk onthouden om te kiezen Android 7+ in de Target Android-apparaten dialoog.

Dit project heeft enkele widgets nodig die behoren tot de Design Support Library, dus open de app module build.gradle bestand en voeg het volgende toe compileren afhankelijkheid ervan:

compileer 'com.android.support:design:26.+'

Druk ten slotte op Synchroniseer nu knop om het project bij te werken.

2. Maak een instellingenactiviteit

In deze zelfstudie maken we een app met een zeer eenvoudige service voor automatisch aanvullen die alleen die invoervelden target waarvoor de gebruiker een e-mailadres moet invoeren. Omdat bijna elke andere app op Google Play vandaag een e-mailadres vraagt, is deze service heel handig.

Onze service moet natuurlijk weten wat de e-mailadressen van de gebruiker zijn. Laten we daarom nu een activiteit bouwen waarbij de gebruiker twee e-mailadressen kan invoeren en opslaan.

Stap 1: Definieer de lay-out

Zoals je zou verwachten, bevat de lay-out van de activiteit er twee Tekst bewerken widgets waar de gebruiker zijn e-mailadressen kan typen. Als u wilt dat het voldoet aan de richtlijnen van Material Design, plaatst u de Tekst bewerken widgets binnen TextInputLayout containers is een goed idee.

Bovendien moet de lay-out een Knop widget die de gebruiker kan indrukken om de e-mailadressen op te slaan.

U bent vrij om de widgets te plaatsen waar u maar wilt. Niettemin, voor nu, stel ik voor dat je ze allemaal in een LinearLayout waarvan de oriëntatie verticaal is.

        

In de bovenstaande code kunt u zien dat de Knop widget heeft een bij klikken attribuut wijst naar een methode. Klik op de gele gloeilamp naast dit attribuut in Android Studio om er een stub voor te maken in de bijbehorende Activiteit klasse.

public void saveEmailAddresses (bekijk weergave) // Meer code zal hier worden toegevoegd

Stap 2: sla de e-mailadressen op

We gebruiken een bestand met gedeelde voorkeuren genaamd EMAIL_STORAGE om onze gegevens te bewaren. U kunt de getSharedPreferences () methode van uw Activiteit klasse om toegang te krijgen tot het bestand. Om het bestand te kunnen schrijven, moet je het ook bellen Bewerk() methode, die een a genereert SharedPreferences.Editor voorwerp.

Voeg daarom de volgende code toe binnen de saveEmailAddresses () methode:

SharedPreferences.Editor-editor = getSharedPreferences ("EMAIL_STORAGE", MODE_PRIVATE) .edit ();

De e-mailadressen ophalen die de gebruiker heeft ingevoerd in de Tekst bewerken widgets, je zult eerst referenties naar hen moeten krijgen met behulp van de findViewById () methode, en bel dan hun getText () methoden.

String primaryEmailAddress = ((EditText) findViewById (R.id.primary)) .getText (). ToString (); String secondaryEmailAddress = ((EditText) findViewById (R.id.secondary)) .getText (). ToString ();

Op dit punt kunt u bellen met putString () methode van de editor om de e-mailadressen toe te voegen aan het voorkeurenbestand als twee sleutelwaardeparen. Nadat u dit gedaan heeft, vergeet niet om de. Te bellen commit () methode om uw wijzigingen permanent te maken.

editor.putString ("PRIMARY_EMAIL", primaryEmailAddress); editor.putString ("SECONDARY_EMAIL", secondaryEmailAddress); editor.commit ();

Stap 3: maak een metadata-bestand aan

De instellingenactiviteit die we in de vorige stap hebben gemaakt, is momenteel slechts een normale activiteit. Om het Android-platform te laten weten dat het een instellingenactiviteit is voor een autofill-service, moeten we een meta-gegevens-XML-bestand maken dat zo zegt.

Maak een nieuw XML-bestand met de naam email_address_filler.xml in de projecten res / xml map. Voeg er binnen een toe  label en stel de waarde ervan in settingsActivity toeschrijven aan de naam van uw Activiteit klasse.

 

U kunt nu de app uitvoeren, twee e-mailadressen typen en op de Opslaan knop om ze op te slaan.

3. Maak een Autofill-service

Elke klasse die het abstract verlengt AutoFillService klas kan dienen als een autofill-service. Dus begin met het maken van een nieuwe Java-klasse met Bestand> Nieuw> Java-klasse. Typ de klas in het dialoogvenster dat verschijnt EmailAddressFiller en zorg ervoor dat u de waarde instelt van de superklasse veld naar AutoFillService.

Android Studio vraagt ​​nu om stubs te genereren voor twee abstracte methoden: onSaveRequest () en onFillRequest (). In deze zelfstudie concentreren we alleen het onFillRequest () methode, die automatisch wordt aangeroepen wanneer de gebruiker een activiteit opent - van alle app-bevattende invoervelden.

@Override public void onFillRequest (AssistStructure assistStructure, Bundle-bundel, CancellationSignal CancellationSignal, FillCallback fillCallback) // Meer code hierheen

Stap 1: Analyseer weergave-hiërarchieën

Een autofill-service moet de gebruikersinterface van een app analyseren en invoervelden identificeren die deze kan invullen. Dat is waarom het onFillRequest () methode ontvangt een AssistStructure object, dat details bevat over alle widgets die momenteel zichtbaar zijn op het scherm. Om precies te zijn, het bevat een boom van ViewNode voorwerpen. 

Als je nog nooit zo'n boom hebt gezien, raad ik je aan de uiautomatorviewer tool, die deel uitmaakt van de Android SDK, om de lay-outhiërarchieën van een paar apps te analyseren. Dit is bijvoorbeeld wat de lay-outhiërarchie van de standaard e-mailapp van Android eruit ziet:

Natuurlijk, om alle knooppunten van een boom te analyseren, hebt u een recursieve methode nodig. Laten we er nu een maken:

void identifyEmailFields (AssistStructure.ViewNode node, List emailFields) // Meer code gaat hier

Zoals u kunt zien, heeft deze methode een ViewNode en een Lijst als zijn parameters. We zullen de gebruiken Lijst om alle invoervelden op te slaan die e-mailadressen verwachten.

U vraagt ​​zich nu misschien af ​​hoe u programmatisch kunt vertellen of een invoerveld een e-mailadres verwacht. Nou, er is echt geen onfeilbare aanpak die je kunt volgen. Voorlopig gaan we ervan uit dat alle app-ontwikkelaars altijd betekenisvolle resource-ID's aan hun invoervelden toevoegen. Op basis van die aanname kunnen we eenvoudig alle invoervelden selecteren waarvan de resource-ID's strings bevatten zoals "email" en "gebruikersnaam".

Voeg daarom de volgende code toe aan de methode:

if (node.getClassName (). bevat ("EditText")) String viewId = node.getIdEntry (); if (viewId! = null && (viewId.contains ("email") || viewId.contains ("username"))) emailFields.add (node); terug te keren; 

Vervolgens telkens wanneer we een ViewNode object dat meer bevat ViewNode objecten, we moeten recursief de identifyEmailFields () methode om al zijn kinderen te analyseren. De volgende code laat zien hoe:

voor (int i = 0; i

Op dit punt kunnen we de identifyEmailFields () methode binnen de onFillRequest () methode en geef het rootknooppunt van de weergavehiërarchie door.

// Maak een lege lijst Lijst emailFields = nieuwe ArrayList <> (); // Vul de lijst identifyEmailFields (assistStructure .getWindowNodeAt (0) .getRootViewNode (), emailFields);

Als onze service geen invoervelden voor e-mails kan identificeren, zou het niets moeten doen. Voeg daarom de volgende code eraan toe:

if (emailFields.size () == 0) terug;

Stap 2: Externe weergaven maken en vullen

Als onze service een invoerveld identificeert dat het kan invullen, moet het een vervolgkeuzelijst vullen die onder het invoerveld wordt weergegeven. Dit is echter niet eenvoudig omdat noch het invoerveld noch de vervolgkeuzelijst bij onze app hoort.

Om de vervolgkeuzelijst te vullen, moeten we gebruiken RemoteViews voorwerpen. Zoals de naam doet vermoeden, een RemoteViews object is een verzameling weergaven die in een andere app kunnen worden weergegeven.

Om een ​​te initialiseren RemoteViews object, hebt u een XML-lay-outbestand nodig. Laten we er een maken die nu wordt genoemd email_suggestion.xml. Voorlopig kan het er maar één bevatten Tekstweergave widget om een ​​e-mailadres weer te geven.

Voeg daarom de volgende code toe aan email_suggestion.xml:

  

U kunt nu teruggaan naar de onFillRequest () methode en maak er twee RemoteViews objecten: één voor de primaire e-mail en één voor de secundaire e-mail.

RemoteViews rvPrimaryEmail = nieuwe RemoteViews (getPackageName (), R.layout.email_suggestion); RemoteViews rvSecondaryEmail = nieuwe RemoteViews (getPackageName (), R.layout.email_suggestion);

De Tekstweergave widgets in de RemoteViews objecten moeten de twee e-mailadressen die we eerder in een bestand met gedeelde voorkeuren hebben opgeslagen, weergeven. Om het bestand te openen, gebruikt u de getSharedPreferences () methode opnieuw. Als het eenmaal is geopend, kunt u het gebruiken getString () methode om beide e-mailadressen op te halen.

Ten slotte, om de inhoud van de afstandsbediening in te stellen Tekstweergave widgets, u moet de setTextViewText () methode.

// Laad de e-mailadressen van voorkeuren SharedPreferences sharedPreferences = getSharedPreferences ("EMAIL_STORAGE", MODE_PRIVATE); String primaryEmail = sharedPreferences.getString ("PRIMARY_EMAIL", ""); String secondaryEmail = sharedPreferences.getString ("SECONDARY_EMAIL", ""); // Update remote TextViews rvPrimaryEmail.setTextViewText (R.id.email_suggestion_item, primaryEmail); rvSecondaryEmail.setTextViewText (R.id.email_suggestion_item, secondaryEmail);

Stap 3: datasets maken

We kunnen de externe weergaven nu gebruiken om gegevenssets voor automatisch aanvullen te maken die naar elke app kunnen worden verzonden. Om ervoor te zorgen dat deze tutorial niet te lang wordt, maken we alleen datasets voor het eerste e-mailinvoerveld dat we tegenkomen. De volgende code laat zien hoe u alleen het eerste e-mailinvoerveld kiest:

AssistStructure.ViewNode emailField = emailFields.get (0);

Een reeks gegevens voor automatisch aanvullen is niets anders dan een instantie van de dataset klasse, en kan worden gebouwd met behulp van de Dataset.Builder klasse.

Wanneer de gebruiker een van de e-mailadressen selecteert die onze service in de vervolgkeuzelijst laat zien, moet deze de inhoud van het bijbehorende invoerveld instellen met behulp van de setValue () methode van de Dataset.Builder klasse. U kunt echter niet slagen voor a ViewNode bezwaar tegen de setValue () methode. Het verwacht eigenlijk een autofill-ID, die moet worden verkregen door de getAutoFillId () methode van de ViewNode voorwerp.

Bovendien moet u de tekst gebruiken die moet worden geschreven in het invoerveld AutoFillValue.forText () methode. De volgende code laat zien hoe:

Dataset primaryEmailDataSet = nieuwe Dataset.Builder (rvPrimaryEmail) .setValue (emailField.getAutoFillId (), AutoFillValue.forText (primaryEmail)) .build (); Dataset secondaryEmailDataSet = nieuwe Dataset.Builder (rvSecondaryEmail) .setValue (emailField.getAutoFillId (), AutoFillValue.forText (secondaryEmail)) .build ();

Voordat u de gegevenssets naar een app verzendt, moet u deze toevoegen aan een FillResponse object, dat kan worden gebouwd met behulp van de FillResponse.Builder klasse. Noem het zijn addDataset () methode twee keer om beide datasets toe te voegen.

Zodra de FillResponse object is gereed, geef het door als argument aan de onSuccess () methode van de FillCallback object, wat een van de parameters is van de onFillRequest () methode.

FillResponse-reactie = nieuwe FillResponse.Builder () .addDataset (primaryEmailDataSet) .addDataset (secondaryEmailDataSet) .build (); fillCallback.onSuccess (respons);

Stap 4: werk het manifest bij

Net als alle services moet de service voor automatisch aanvullen ook in het project worden aangegeven AndroidManifest.xml het dossier. Terwijl u dit doet, moet u ervoor zorgen dat deze wordt beschermd door de android.permission.BIND_AUTO_FILL toestemming.

Deze service heeft ook een  tag waarmee het kan reageren op de android.service.autofill.AutoFillService actie, en a tag die verwijst naar het XML-bestand met metadata dat we in een eerdere stap hebben gemaakt.

Voeg daarom de volgende regels toe aan uw manifestbestand:

     

Onze autofill-service en -app zijn nu klaar. Bouw het project en installeer de app op uw apparaat.

4. Activeer en gebruik de Autofill-service

Om de autofill-service te activeren, opent u uw apparaat instellingen app en navigeer naar Apps & meldingen> Geavanceerd> Standaard apps> app Automatisch aanvullen. Selecteer in het volgende scherm uw app in de lijst met beschikbare apps voor automatisch aanvullen.

U kunt nu elke app openen die om een ​​e-mailadres vraagt ​​om uw service voor automatisch aanvullen in actie te zien. Dit is bijvoorbeeld wat u zou zien op de inlogschermen van Instagram en Pinterest:

Conclusie

U weet nu hoe u een aangepaste autofill-service voor Android kunt maken en gebruiken. Voel je vrij om het uit te breiden om andere gemeenschappelijke velden te ondersteunen, zoals voornaam of telefoonnummer. U kunt ook proberen invoervelden te identificeren met behulp van andere kenmerken, zoals labels en hints.

Raadpleeg de officiële documentatie voor meer informatie over het kader voor automatisch aanvullen. En bekijk in de tussentijd een aantal van onze andere berichten over de ontwikkeling van Android O en Android-apps!