Kode en widget for Android-appen din Oppdaterer widgeten

Applikasjons widgets gir brukerne enkel tilgang til programmets mest brukte funksjoner, samtidig som appen din blir til stede på brukerens startskjerm. Ved å legge til en widget i prosjektet ditt, kan du gi en bedre brukeropplevelse, mens du oppfordrer brukerne til å forbli forlovet med søknaden din, da hver gang de ser på deres startskjerm, ser de widgeten din, viser noen av appens mest nyttige og interessant innhold.

I denne tre delserien bygger vi en applikasjons widget som har all funksjonalitet du finner i ganske mye hver Android applikasjons widget. 

I det første innlegget opprettet vi en widget som henter og viser data, og utfører en unik handling som svar på ved trykk arrangementer. Men vår widget mangler fortsatt en viktig del av funksjonaliteten: den aldri oppdateringer med ny informasjon. En widget som aldri har noe nytt å tilby, er ikke så nyttig, så vi gir vår widget to forskjellige måter å oppdatere. 

Ved slutten av denne serien har vi utvidet vår widget for å hente og vise nye data automatisk basert på en tidsplan, og som svar på brukerinteraksjon.

Vi plukker opp akkurat der vi sluttet, så hvis du ikke har en kopi av widgeten vi opprettet i det første innlegget, kan du laste det ned fra GitHub.

Oppdaterer oppsettet ditt

Det første trinnet er å oppdatere vårt layout for å vise noen data som endres over tid. For å hjelpe oss med å se nøyaktig når widgeten vår mottar hver oppdatering, skal jeg instruere widgeten for å hente og vise gjeldende tid, når den utfører en oppdatering. 

Jeg skal legge til følgende i widgetoppsettet: 

  • EN TextView som viser a Siste oppdatering merkelapp.
  • EN TextView som viser tidspunktet for den siste oppdateringen.

Mens vi jobber på new_app_widget.xml fil, jeg skal også legge til TextView Dette vil etter hvert tillate brukeren å utløse en oppdatering manuelt: 

      // Legg til en 'Trykk for å oppdatere' Tekstvisning //   // Legg til en TextView som viser vår 'Siste oppdatering' etikett //  // Legg til TextView som viser tidspunktet for den siste oppdateringen //    

Definer deretter de nye strengressursene som vi refererer til i vårt oppsett: 

Trykk for å oppdatere Siste oppdatering % 1 $ s

De @ Snor / tids ser annerledes ut enn den typiske strengen din, da det bare er en plassholder som vil bli erstattet ved kjøretid.

Dette gir oss det ferdige oppsettet:

Oppdaterer Widget Basert på et tidsplan 

Siden det er den enkleste metoden å implementere, skal jeg begynne å oppdatere vår widget automatisk, etter at en bestemt tidsperiode er gått. 

Når du lager denne typen automatisk oppdateringsplan, er 1800000 millisekunder (30 minutter) det minste intervallet du kan bruke. Selv om du setter prosjektet ditt updatePeriodMillis til mindre enn 30 minutter, vil widgeten din fortsatt Oppdater bare en gang hver halvtime.

Bestemme hvor ofte widgeten din skal oppdatere, er aldri grei. Hyppige oppdateringer er større drenering på enhetens batteri, men sett disse oppdateringene for langt fra hverandre, og widgeten din kan komme opp med å vise betydelig utdatert informasjon til brukeren.

For å finne en balanse som fungerer for ditt eget prosjekt, må du teste din widget over en rekke oppdateringsfrekvenser, og måle hvilken effekt hver frekvens har på batteriets levetid, mens du overvåker om widgetens innhold aldri blir merkbart utdatert. 

Siden hyppig er-for-hyppig er et av de frustrerende subjektive spørsmålene der det ikke er noe "riktig" svar, kan det bidra til å få en annen mening ved å arrangere noen brukertesting. Du kan til og med sette opp noen A / B-testing for å sjekke om visse oppdateringsfrekvenser mottas mer positivt enn andre. 

Åpne prosjektet ditt AppWidgetProviderInfo fil (res / xml / new_app_widget_info.xml) og du vil se at den allerede definerer et standard oppdateringsintervall på 86400000 millisekunder (24 timer). 

android: updatePeriodMillis = "86400000"

Det er mange widgets som bare oppdateres en gang i døgnet, for eksempel kan en widget som viser værmeldingen bare ha behov for å hente ny informasjon en gang per dag. Men selv om widgeten din bare trenger å oppdatere en gang per dag, er dette ikke ideelt når du tester appen din. Ingen ønsker å vente 24 timer bare for å se om deres onUpdate () Metoden utløses på riktig måte, så du vil vanligvis bruke det kortest mulige intervallet når du utfører første test, og deretter endre denne verdien senere, hvis nødvendig.

For å gjøre det enklere å teste appen vår, skal jeg bruke det minste mulige intervallet: 

android: updatePeriodMillis = "1800000"

Henter og viser nåværende tid 

De onUpdate () Metoden er ansvarlig for oppdateringen av widgeten din Visninger med ny informasjon. Hvis du åpner prosjektets widgetleverandør (java / verdier / NewAppWidget.java) så ser du at den allerede inneholder oversikten over en onUpdate () metode: 

 @Override public void onUpdate (Kontekst kontekst, AppWidgetManager appWidgetManager, int [] appWidgetIds) // Det kan være flere widgets aktive, så oppdater dem alle // for (int appWidgetId: appWidgetIds) updateAppWidget (kontekst, appWidgetManager, appWidgetId) ; 

Uansett om widgeten din oppdateres automatisk eller som svar på brukerinteraksjon, er oppdateringsprosessen nøyaktig den samme: widget-sjefen sender en kringkastingsformål med ACTION_APPWIDGET_UPDATE handling, og widget-leverandør-klassen reagerer ved å ringe onUpdate () metode, som igjen kalles updateAppWidget () hjelpemetode. 

Når vi har oppdatert vår NewAppWidget.java klasse for å hente og vise gjeldende tid, vil prosjektet bruke samme del av koden uansett hvordan onUpdate () Metoden utløses: 

importer android.appwidget.AppWidgetManager; importer android.appwidget.AppWidgetProvider; importer android.content.Context; importer android.widget.RemoteViews; importer android.app.PendingIntent; importer android.content.Intent; importer android.net.Uri; importer java.text.DateFormat; importer java.util.Date; offentlig klasse NewAppWidget utvider AppWidgetProvider static void updateAppWidget (Kontekst kontekst, AppWidgetManager appWidgetManager, int appWidgetId) // Hent tiden // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (nytt dato ()); // Konstruer RemoteViews-objektet // RemoteViews visninger = nye RemoteViews (context.getPackageName (), R.layout.new_app_widget); views.setTextViewText (R.id.id_value, String.valueOf (appWidgetId)); // Hent og vis tidspunktet // views.setTextViewText (R.id.update_value, context.getResources (). GetString (R.string.time, timeString)); Intent Intent = Ny Intent (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivity (kontekst, 0, intensjon, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); appWidgetManager.updateAppWidget (appWidgetId, visninger);  @Override public void onUpdate (Kontekst kontekst, AppWidgetManager appWidgetManager, int [] appWidgetIds) // Hvis flere widgets er aktive, oppdater deretter dem alle // for (int appWidgetId: appWidgetIds) updateAppWidget (kontekst, appWidgetManager, appWidgetId);  

Det er ett problem med koden ovenfor: hvis brukeren tapper TextView flere ganger i løpet av et minutt, blir det ingen visuell indikasjon på at widgeten har oppdatert, ganske enkelt fordi det ikke er noe nytt å vise. Dette vil trolig ikke føre til problemer for sluttbrukerne dine, som ikke er sannsynlig å sitte der, trykke på TextView flere ganger i minuttet og lurer på hvorfor tiden ikke har endret seg. Dette kan imidlertid være et problem når du tester appen din, da det betyr at du må vente minst 60 sekunder mellom å utløse onUpdate () metode. 

For å sikre at det alltid er noen form for visuell bekreftelse på at onUpdate () Metoden har løpt med hell, jeg skal vise en skål hver gang onUpdate () er kalt: 

importere android.widget.Toast; ... @Override public void onUpdate (Kontekst kontekst, AppWidgetManager appWidgetManager, int [] appWidgetIds) for (int appWidgetId: appWidgetIds) updateAppWidget (kontekst, appWidgetManager, appWidgetId); Toast.makeText (kontekst, "Widget har blitt oppdatert!", Toast.LENGTH_SHORT) .show (); 

Oppdaterer widgeten din som svar på brukerhandling

Vår widget oppdateres nå automatisk en gang hver halvtime, men hva med oppdatering som svar på brukerinteraksjon? 

Vi har allerede lagt mye grunnlag ved å legge til en Trykk for å oppdatere TextView til vårt layout og utvide NewAppWidget.java klassen for å hente og vise gjeldende tid hver gang onUpdate () er kalt.

Det eneste du må gjøre er å lage en Intent med AppWidgetManager.ACTION_APPWIDGET_UPDATE, som er en handling som informerer widgeten om at det er på tide å oppdatere, og deretter ringe denne hensikten som svar på brukeren som interagerer med Trykk for å oppdatere TextView

Her er det ferdige NewAppWidget.java klasse:

importer android.appwidget.AppWidgetManager; importer android.appwidget.AppWidgetProvider; importer android.content.Context; importer android.widget.RemoteViews; importer android.app.PendingIntent; importer android.content.Intent; importer android.net.Uri; importer java.text.DateFormat; importer java.util.Date; importer android.widget.Toast; offentlig klasse NewAppWidget utvider AppWidgetProvider static void updateAppWidget (Kontekst kontekst, AppWidgetManager appWidgetManager, int appWidgetId) // Hent gjeldende tid // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (nytt dato ()); RemoteViews visninger = nye RemoteViews (context.getPackageName (), R.layout.new_app_widget); views.setTextViewText (R.id.id_value, String.valueOf (appWidgetId)); views.setTextViewText (R.id.update_value, context.getResources (). getString (R.string.time, timeString)); // Opprett en hensikt med AppWidgetManager.ACTION_APPWIDGET_UPDATE handlingen // Intent intentUpdate = new Intent (kontekst, NewAppWidget.class); intentUpdate.setAction (AppWidgetManager.ACTION_APPWIDGET_UPDATE); // Oppdater bare den gjeldende widget-forekomsten ved å opprette en matrise som inneholder widgetens unike ID // int [] idArray = new int [] appWidgetId; intentUpdate.putExtra (AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray); // Wrap hensikten som en PendingIntent, ved hjelp av PendingIntent.getBroadcast () // PendingIntent pendingUpdate = PendingIntent.getBroadcast (kontekst, appWidgetId, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT); // Send den ventende hensikten som svar på brukeren og trykke på 'Oppdater' TextView // views.setOnClickPendingIntent (R.id.update, pendingUpdate); Intent Intent = Ny Intent (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivity (kontekst, 0, intensjon, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); // Be om at AppWidgetManager oppdaterer programgrensesnittet // appWidgetManager.updateAppWidget (appWidgetId, visninger);  @Override public void onUpdate (Kontekst kontekst, AppWidgetManager appWidgetManager, int [] appWidgetIds) for (int appWidgetId: appWidgetIds) updateAppWidget (kontekst, appWidgetManager, appWidgetId); Toast.makeText (kontekst, "Widget har blitt oppdatert!", Toast.LENGTH_SHORT) .show (); 

Å kunne oppdatere en widget på forespørsel kan være uvurderlig når du tester prosjektet ditt, da det betyr at du aldri må vente på at oppdateringsintervallet skal gå. Selv om du ikke inkluderer denne funksjonaliteten i det ferdige programmet, kan det hende du vil legge til en midlertidig Trykk for å oppdatere knappen, bare for å gjøre livet enklere når du tester prosjektet ditt. 

Opprette et forhåndsvisningsbilde 

Vår widget ser nå ut helt forskjellig fra widgeten som Android Studio genererte for oss automatisk, men for øyeblikket bruker den fremdeles det forhåndsdefinerte forhåndsvisningsbildet.

Ideelt sett bør forhåndsvisningsbildet oppfordre brukere til å velge widgeten din fra Widget Picker, men i det minste bør det være en nøyaktig representasjon av hvordan widgeten din faktisk ser ut! For øyeblikket merker forhåndsvisningsbildet vårt ingen av disse boksene, så vi må lage en ny. 

Den enkleste metoden er å bruke Widget Preview applikasjon som er inkludert i Android-emulatoren.

Opprette en widget forhåndsvisning

Først installerer du prosjektet ditt på en Android Virtual Device (AVD). Åpne deretter AVDs applader og start programmet Widget Preview. AVD vil vise en liste over alle apper som er installert på enheten - velg appen din fra listen. 

Din widget vil bli vist på en tom bakgrunn. Tilbring litt tid på å endre størrelse og justere widgeten din slik at den ser best ut, og når du er fornøyd med resultatene, velg Ta et øyeblikksbilde. Skjermbildet vil bli lagret som en PNG i AVDs nedlasting mappe. For å hente denne filen, bytt tilbake til Android Studio og åpne Enhetsfilutforsker, ved å velge Se> Verktøy Windows> Enhetsfilutforsker fra verktøylinjen. I visningen Device File Explorer, naviger til sdcard / Last ned mappe, hvor du finner forhåndsvisningsbildet lagret som: [App_name] _ori_ [orientering] PNG

Dra dette bildet ut av Android Studio og slipp det et sted som er lett tilgjengelig, for eksempel skrivebordet ditt. Gi bildet et mer beskrivende navn, og dra og slipp bildet i prosjektet ditt teikne mappe. Nå kan du åpne AppWidgetProviderInfo fil (i dette tilfellet er det new_app_widget_info.xml) og endre følgende linje for å referere til det nye forhåndsvisningsbildet ditt: 

 android: previewImage = "@ trekkbare / example_appwidget_preview"

Til slutt kan du fjerne unødvendig example_appwidget_preview trekkes fra prosjektet ditt. 

Teste Widget

Det er på tide å sette den ferdige widgeten på prøve!

Først installerer du det oppdaterte prosjektet på din fysiske Android-enhet eller AVD. Fjern alle eksisterende forekomster av denne widgeten fra din startskjerm, så du vet du jobber med den nyeste versjonen. 

Hvis du vil legge til widgeten din, trykker du på et tomt mellomrom på startskjermen, banker på Widget og velg deretter widgeten din. Du får muligheten til å endre størrelsen og plassere widgeten, etter behov. 

De Siste oppdatering verdien vil vise tiden du opprettet denne widgeten. trykk Trykk for å oppdatere og widgeten skal vise en skål og en ny tid. Hvis du plasserer en andre forekomst av widgeten på startskjermen, bør den vise en annen tid til den første. 

Du kan oppdatere en av disse widget-instansene ved å gi den Trykk for å oppdatere TextView en kran. Hvis du utløser en manuell oppdatering for den første widgeten, blir den andre widgeten ikke oppdatert, og omvendt. 

I tillegg til manuelle oppdateringer, oppdaterer App Widget Manager alle forekomster av widgeten en gang hvert 30. minutt, basert på tidspunktet da du opprettet første instans. Selv om manuelle oppdateringer kan føre til at det vises forskjellige tidspunkter, vil hver gang en halv time alle forekomster bli oppdatert samtidig, da vises de samtidig.

Du vil kanskje beholde noen få eksempler på denne widgeten på startskjermbildet, slik at du kan overvåke hvordan innholdet endres over tid som følge av en kombinasjon av automatiske og manuelle oppdateringer.

Konklusjon

I denne serien har vi opprettet en Android-applikasjons-widget som demonstrerer hvordan du implementerer alle de vanligste funksjonene som finnes i app-widgets. Hvis du har fulgt sammen siden begynnelsen, så har du nå bygget en widget som oppdateres automatisk og som respons på brukerinngang, og som er i stand til å reagere på onClick-hendelser (du kan også laste ned hele prosjektet fra GitHub ). 

I neste innlegg ser vi på noen gode metoder for å sikre at widgeten din gir en god brukeropplevelse, og hvordan du forbedrer widgeten din med en konfigurasjonsaktivitet.