Codificați un widget pentru aplicația Android Actualizați widgetul

Widgeturile pentru aplicații oferă utilizatorilor acces ușor la caracteristicile cele mai frecvent utilizate ale aplicației dvs., oferind în același timp aplicației dvs. o prezență pe ecranul inițial al utilizatorului. Prin adăugarea unui widget în proiectul dvs., puteți oferi o experiență mai bună pentru utilizatori, încurajând în același timp utilizatorii să rămână angajați în aplicația dvs., deoarece de fiecare dată când se uită la ecranul inițial, vă vor vedea widget-ul, afișând unele dintre cele mai utile și conținut interesant.

În această serie de trei părți, construim un widget de aplicație care are toată funcționalitatea pe care o veți găsi destul de mult fiecare Aplicație widget Android. 

În primul mesaj, am creat un widget care preia și afișează date și efectuează o acțiune unică ca răspuns la onClick evenimente. Cu toate acestea, widgetul nostru lipsește încă o piesă crucială de funcționalitate: acesta nu actualizări cu informații noi. Un widget care nu are nimic nou de oferit nu este tot atât de util, așa că vom da miniaplicația noastră Două modalități diferite de actualizare. 

Până la sfârșitul acestei serii, ne-am extins widget-ul pentru a prelua și afișa automat date noi în funcție de program, și ca răspuns la interacțiunea utilizatorului.

Mergem chiar acolo unde am rămas, deci dacă nu aveți o copie a widget-ului creat în prima postare, atunci îl puteți descărca de la GitHub.

Actualizați aspectul

Primul pas este actualizarea layout-ului nostru pentru a afișa unele date care se schimbă în timp. Pentru a ne ajuta să vedem exact când widget-ul nostru primește fiecare actualizare, voi instrui widget-ul să preia și să afișeze ora curentă, ori de câte ori efectuează o actualizare. 

Voi adăuga următoarele elemente în aspectul widget: 

  • A TextView care afișează a Ultima actualizare eticheta.
  • A TextView care va afișa ora ultimei actualizări.

În timp ce lucrăm la new_app_widget.xml fișier, voi adăuga, de asemenea TextView care va permite în cele din urmă utilizatorului să declanșeze manual o actualizare: 

      // Adăugați un "Apăsați pentru a actualiza" TextView //   // Adăugați un TextView care va afișa eticheta noastră "Ultima actualizare" //  // Adăugați TextView care va afișa ora ultimei actualizări //    

Apoi, definiți noile resurse de șir pe care le menționăm în aspectul nostru: 

Atingeți pentru actualizare Ultima actualizare % 1 $ s

@ String / time arată diferit de șirul dvs. tipic, deoarece este doar un substituent care va fi înlocuit în timpul rulării.

Acest lucru ne oferă aspectul final:

Actualizarea widgetului dvs. pe baza unei planificări 

Deoarece este cea mai ușoară metodă de a implementa, o să încep prin actualizarea automată a widget-ului, după o perioadă de timp stabilită. 

Când creați acest tip de program de actualizare automată, 1800000 de milisecunde (30 de minute) este cel mai mic interval pe care îl puteți utiliza. Chiar dacă setați proiectul updatePeriodMillis la mai puțin de 30 de minute, widget-ul va încă actualizați doar o dată la fiecare jumătate de oră.

Deciderea frecvenței actualizării widget-ului dvs. nu este niciodată simplă. Actualizările frecvente reprezintă o scurgere mai mare a bateriei dispozitivului, însă aceste actualizări sunt prea îndepărtate, iar widget-ul dvs. se poate termina să afișeze în mod semnificativ informații necunoscute utilizatorului.

Pentru a găsi un echilibru care funcționează pentru proiectul dvs. special, va trebui să testați widget-ul pe o serie de frecvențe de actualizare și să măsurați impactul pe care fiecare frecvență îl are asupra duratei de viață a bateriei, monitorizând totodată dacă conținutul widget-ului devine evident depășit. 

Din moment ce frecvența este prea frecventă este una dintre acele întrebări subiective frustrante în care nu există un răspuns "corect", poate ajuta la obținerea unei a doua opinii prin organizarea unor teste de utilizator. Ați putea chiar să configurați unele teste A / B pentru a verifica dacă anumite frecvențe de actualizare sunt recepționate mai pozitiv decât altele. 

Deschideți proiectul AppWidgetProviderInfo fișier (res / xml / new_app_widget_info.xml) și veți vedea că acesta definește deja un interval de actualizare implicit de 86400000 milisecunde (24 de ore). 

Android: updatePeriodMillis = "86400000"

Există o mulțime de widget-uri care se actualizează doar o dată la 24 de ore, de exemplu un widget care afișează prognoza meteo ar putea avea nevoie doar de recuperarea informațiilor noi o dată pe zi. Cu toate acestea, chiar dacă widgetul dvs. trebuie doar să se actualizeze o dată pe zi, acest lucru nu este ideal atunci când testați aplicația. Nimeni nu vrea să aștepte 24 de ore doar pentru a vedea dacă ei onUpdate () metoda declanșează corect, astfel încât, în mod obișnuit, să utilizați intervalul cel mai scurt posibil la efectuarea testelor inițiale și apoi să modificați mai târziu această valoare, dacă este necesar.

Pentru a face mai ușoară testarea aplicației, voi folosi cel mai mic interval posibil: 

Android: updatePeriodMillis = "1800000"

Recuperarea și afișarea timpului curent 

onUpdate () metoda este responsabilă pentru actualizarea widget-urilor Vizualizări cu informații noi. Dacă deschideți furnizorul de widgeturi al proiectului (java / valori / NewAppWidget.java), veți vedea că acesta conține deja conturul unui onUpdate () metodă: 

 @Override public void onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) // Pot exista mai multe widget-uri active, deci actualizați-le pe toate // pentru (int appWidgetId: appWidgetIds) updateAppWidget (context, appWidgetManager, appWidgetId) ; 

Indiferent dacă widget-ul dvs. se actualizează în mod automat sau ca răspuns la interacțiunea utilizatorului, procesul de actualizare este exact același: managerul de widget-uri trimite o intenție de difuzare cu ACTION_APPWIDGET_UPDATE acțiune, iar clasa widget-provider răspunde apelând onUpdate () , care la rândul său numește updateAppWidget () metoda helper. 

Odată ce ne-am actualizat NewAppWidget.java clasa pentru a prelua și afișa ora curentă, proiectul nostru va folosi aceeași secțiune de cod, indiferent de modul în care onUpdate () metoda este declanșată: 

import șiroid.appwidget.AppWidgetManager; import șiroid.appwidget.AppWidgetProvider; importați android.content.Context; importă android.widget.RemoteViews; import șiroid.app.PendingIntent; import șiroid.content.Intent; importul android.net.Uri; import java.text.DateFormat; import java.util.Date; clasa publica NewAppWidget extinde AppWidgetProvider static void updateAppWidget (Context context, AppWidgetManager appWidgetManager, int appWidgetId) // Returna timpului // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (new Date ()); // Construiește obiectul RemoteViews // Vizualizări RemoteViews = noi RemoteViews (context.getPackageName (), R.layout.new_app_widget); views.setTextViewText (R.id.id_value, String.valueOf (appWidgetId)); // Returnați și afișați ora // views.setTextViewText (R.id.update_value, context.getResources (). GetString (R.string.time, timeString)); Intenția intenției = intenția nouă (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivitate (context, 0, intenție, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); appWidgetManager.updateAppWidget (appWidgetId, vizualizări);  @Override public void onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) // Dacă mai multe widgeturi sunt active, actualizați-le pe toate pentru // pentru (int appWidgetId: appWidgetIds) updateAppWidget (context, appWidgetManager, appWidgetId);  

Există o problemă cu codul de mai sus: dacă utilizatorul dă click pe TextView de mai multe ori în decursul unui minut, nu va exista nici o indicație vizuală că widget-ul a fost actualizat, pur și simplu pentru că nu există timp nou pentru a fi afișat. Acest lucru probabil că nu va cauza probleme utilizatorilor finali, care este puțin probabil să stea acolo, atingând TextView de mai multe ori pe minut și întrebându-se de ce timpul nu sa schimbat. Cu toate acestea, aceasta poate fi o problemă atunci când testați aplicația dvs., deoarece înseamnă că va trebui să așteptați cel puțin 60 de secunde între declanșarea onUpdate () metodă. 

Pentru a vă asigura că există întotdeauna un fel de confirmare vizuală onUpdate () metoda a fugit cu succes, voi afișa un pâine oricând onUpdate () se numește: 

importul șiroid.widget.Toast; ... @Override public void onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) pentru (int appWidgetId: appWidgetIds) updateAppWidget (context, appWidgetManager, appWidgetId); Toast.makeText (context, "Widgetul a fost actualizat!", Toast.LENGTH_SHORT) .show (); 

Actualizarea widgetului dvs. ca răspuns la acțiunea utilizatorului

Widget-ul nostru se va actualiza automat o dată la fiecare jumătate de oră, dar despre actualizarea ca răspuns la interacțiunea cu utilizatorul? 

Am stabilit deja o mulțime de teme prin adăugarea unui Atingeți pentru Actualizare TextView la aspectul nostru și extinderea NewAppWidget.java pentru a recupera și a afișa ora curentă ori de câte ori onUpdate () se numește.

Singurul lucru pe care trebuie să-l faci este să creezi un scop cu AppWidgetManager.ACTION_APPWIDGET_UPDATE, care este o acțiune care informează widget-ul că este timpul să se actualizeze și apoi să numească acest Intent ca răspuns la interacțiunea utilizatorului cu Atingeți pentru Actualizare TextView

Iată cele finalizate NewAppWidget.java clasă:

import șiroid.appwidget.AppWidgetManager; import șiroid.appwidget.AppWidgetProvider; importați android.content.Context; importă android.widget.RemoteViews; import șiroid.app.PendingIntent; import șiroid.content.Intent; importul android.net.Uri; import java.text.DateFormat; import java.util.Date; importă android.widget.Toast; clasa publica NewAppWidget extinde AppWidgetProvider static void updateAppWidget (Context context, AppWidgetManager appWidgetManager, int appWidgetId) // Returnati timpul curent // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (new Date ()); RemoteViews views = noi 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)); // Creați o intenție cu acțiunea AppWidgetManager.ACTION_APPWIDGET_UPDATE // intenția intentUpdate = intenția nouă (context, NewAppWidget.class); intentUpdate.setAction (AppWidgetManager.ACTION_APPWIDGET_UPDATE); // Actualizați numai instanța widgetului curent, creând un tabel care conține ID-ul unic al widgetului // int [] idArray = new int [] appWidgetId; intentUpdate.putExtra (AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray); // Înfășurați intenția ca PendingIntent, utilizând PendingIntent.getBroadcast () // PendingIntent pendingUpdate = PendingIntent.getBroadcast (context, appWidgetId, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT); // Trimite intenția în așteptare ca răspuns la utilizatorul care atinge "Update" TextView // views.setOnClickPendingIntent (R.id.update, pendingUpdate); Intenția intenției = intenția nouă (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivitate (context, 0, intenție, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); // Solicitați ca AppWidgetManager să actualizeze widgetul aplicației // appWidgetManager.updateAppWidget (appWidgetId, vizualizări);  @Override public void onUpdate (Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) pentru (int appWidgetId: appWidgetIds) updateAppWidget (context, appWidgetManager, appWidgetId); Toast.makeText (context, "Widgetul a fost actualizat!", Toast.LENGTH_SHORT) .show (); 

Fiind capabil să actualizeze un widget la cerere poate fi de neprețuit atunci când testarea proiectului dvs., deoarece înseamnă că nu va trebui să așteptați pentru intervalul de actualizare să treacă. Chiar dacă nu includeți această funcție în aplicația finită, vă recomandăm să adăugați o perioadă temporară Atingeți pentru Actualizare , pentru a vă ușura viața atunci când vă testați proiectul. 

Crearea unei imagini de previzualizare 

Widgetul nostru arată acum complet diferit de widget-ul pe care Android Studio la generat automat pentru noi, dar în prezent utilizează în continuare imaginea de previzualizare generată automat.

În mod ideal, imaginea de previzualizare ar trebui să încurajeze utilizatorii să vă aleagă widget-ul de la widgetul Picker, dar cel puțin ar trebui să fie o reprezentare exactă a modului în care arată widget-ul dvs. de fapt! În prezent, imaginea noastră de previzualizare bate nici din acele casete, așa că trebuie să creați unul nou. 

Cea mai ușoară metodă este de a utiliza Previzualizare widget aplicație inclusă în emulatorul Android.

Crearea unei previzualizări widget

Mai întâi, instalați-vă proiectul pe un dispozitiv virtual Android (AVD). Apoi deschideți sertarul de aplicații AVD și lansați aplicația de previzualizare widget. AVD va afișa o listă a fiecărei aplicații instalate pe dispozitiv - selectați aplicația din listă. 

Widget-ul dvs. va fi afișat pe fundal gol. Petreceți ceva timp redimensionând și ajustând widgetul astfel încât acesta să arate cel mai bine și, odată ce sunteți mulțumit de rezultate, selectați Faceți Snapshot. Imaginea de ecran va fi salvată ca PNG în AVD Descarca pliant. Pentru a prelua acest fișier, reveniți la Android Studio și deschideți Dispozitiv de File Explorer, prin selectarea Vizualizare> Instrument Windows> Device File Explorer din bara de instrumente. În ecranul Device File Explorer, navigați la sdcard / Descărcare , unde veți găsi imaginea de previzualizare salvată ca: [App_name] _ori_ [orientare] .png

Glisați această imagine din Android Studio și plasați-o undeva ușor accesibilă, cum ar fi desktop-ul dvs. Dați imaginii un nume mai descriptiv, apoi glisați și fixați imaginea în proiectul dvs. drawable pliant. Acum poți deschide AppWidgetProviderInfo fișier (în acest caz, asta e new_app_widget_info.xml) și modificați următoarea linie pentru a face referire la noua imagine de previzualizare: 

 android: previewImage = "@ drawable / example_appwidget_preview"

În cele din urmă, puteți elimina datele inutile example_appwidget_preview tractată din proiectul dvs.. 

Testați-vă widgetul

Este timpul să puneți widgetul final la test!

Mai întâi, instalați proiectul actualizat pe dispozitivul fizic Android sau AVD. Eliminați toate instanțele existente ale acestui widget de pe ecranul dvs. de pornire, așa că dvs. ști lucrați cu cea mai recentă versiune. 

Pentru a adăuga widgetul dvs., apăsați orice spațiu gol de pe ecranul inițial, apăsați Widget apoi selectați widgetul. Veți avea ocazia să redimensionați și să repoziționați widget-ul, după cum este necesar. 

Ultima actualizare valoare va afișa timpul pe care l-ați creat acest widget. presa Atingeți pentru Actualizare și widget-ul ar trebui să afișeze un pâine prăjită și un timp nou. Dacă plasați oa doua instanță a widget-ului pe ecranul dvs. inițial, acesta ar trebui să afișeze un timp diferit față de primul. 

Aveți posibilitatea să actualizați oricare dintre aceste instanțe widget, dând acestuia Atingeți pentru Actualizare TextView un robinet. Dacă declanșați o actualizare manuală pentru primul widget, atunci al doilea widget nu va fi actualizat și invers. 

În plus față de actualizările manuale, App Widget Manager se va actualiza toate instanțe ale widget-ului dvs. o dată la fiecare 30 de minute, în funcție de momentul creării primei instanțe. Deși actualizările manuale pot avea ca rezultat instanțe care afișează momente diferite, o dată la fiecare jumătate de oră toate instanțele vor fi actualizate simultan, moment în care vor fi afișate în același timp.

Poate doriți să păstrați câteva instanțe ale acestui widget pe ecranul dvs. de pornire, astfel încât să puteți monitoriza modul în care conținutul lor se schimbă în timp ca răspuns la o combinație de actualizări automate și manuale.

Concluzie

În această serie, am creat un widget pentru aplicații Android care demonstrează modul de implementare a celor mai frecvente funcții găsite în widgeturile aplicației. Dacă ați urmărit de-a lungul timpului de la început, apoi ați construit un widget care se actualizează în mod automat și ca răspuns la intrarea utilizatorului și care este capabil să reacționeze la evenimentele onClick (de asemenea, puteți descărca proiectul complet de la GitHub ). 

În următoarea postare, vom examina câteva exemple de bune practici pentru a vă asigura că widgetul dvs. oferă o experiență bună pentru utilizatori și cum să vă îmbunătățiți widgetul cu o configurație Activitate.

Cod