I widget dell'applicazione consentono ai tuoi utenti di accedere facilmente alle funzioni più utilizzate della tua applicazione, dando allo stesso tempo una presenza sulla schermata principale dell'utente. Aggiungendo un widget al tuo progetto, puoi fornire un'esperienza utente migliore, incoraggiando gli utenti a rimanere impegnati con la tua applicazione, poiché ogni singola volta che guardano la schermata iniziale vedranno il tuo widget, visualizzando alcune delle tue app più utili e contenuto interessante.
In questa serie di tre parti, stiamo costruendo un widget di applicazione che ha tutte le funzionalità che troverai in più o meno ogni Widget dell'applicazione Android.
Nel primo post, abbiamo creato un widget che recupera e visualizza dati ed esegue un'azione unica in risposta a al clic
eventi. Tuttavia, al nostro widget manca ancora un elemento cruciale di funzionalità: esso mai aggiornamenti con nuove informazioni. Un widget che non ha mai nulla di nuovo da offrire non è poi così utile, quindi daremo il nostro widget Due diversi modi per aggiornare.
Entro la fine di questa serie, avremo ampliato il nostro widget per recuperare e visualizzare automaticamente i nuovi dati in base a una pianificazione, e in risposta all'interazione dell'utente.
Stiamo riprendendo da dove eravamo rimasti, quindi se non hai una copia del widget che abbiamo creato nel primo post, puoi scaricarlo da GitHub.
Il primo passo è l'aggiornamento del layout per visualizzare alcuni dati che cambiano nel tempo. Per aiutarci a vedere esattamente quando il nostro widget riceve ogni aggiornamento, ho intenzione di istruire il widget per recuperare e visualizzare l'ora corrente, ogni volta che esegue un aggiornamento.
Ho intenzione di aggiungere il seguente al layout del widget:
TextView
che mostra a Ultimo aggiornamento etichetta.TextView
che visualizzerà l'ora dell'ultimo aggiornamento.Mentre stiamo lavorando su new_app_widget.xml file, aggiungerò anche il TextView
che alla fine consentirà all'utente di attivare manualmente un aggiornamento:
// Aggiungi un 'Tap per aggiornare' TextView // // Aggiungi una TextView che mostrerà la nostra etichetta 'Ultimo aggiornamento' // // Aggiungi il TextView che visualizzerà l'ora dell'ultimo aggiornamento //
Quindi, definisci le nuove risorse stringa che facciamo riferimento nel nostro layout:
Tocca per aggiornare Ultimo aggiornamento % 1 $ s
Il @ String / ora
sembra diverso dalla tua stringa tipica, in quanto è solo un segnaposto che verrà sostituito in fase di runtime.
Questo ci dà il layout finito:
Poiché è il metodo più semplice da implementare, inizierò aggiornando automaticamente il nostro widget, dopo che è trascorso un determinato periodo di tempo.
Quando si crea questo tipo di programma di aggiornamento automatico, 1800000 millisecondi (30 minuti) è l'intervallo più piccolo che è possibile utilizzare. Anche se hai impostato il tuo progetto updatePeriodMillis
a meno di 30 minuti, il widget sarà ancora aggiornare solo una volta ogni mezz'ora.
Decidere la frequenza con cui il tuo widget dovrebbe aggiornarsi non è mai semplice. Gli aggiornamenti frequenti sono un maggiore drenaggio della batteria del dispositivo, ma impostano questi aggiornamenti troppo distanti e il tuo widget potrebbe finire con la visualizzazione di informazioni significativamente obsolete all'utente.
Per trovare un equilibrio che funzioni per il tuo particolare progetto, dovrai testare il tuo widget su una gamma di frequenze di aggiornamento e misurare l'impatto di ciascuna frequenza sulla durata della batteria, controllando al contempo se il contenuto del widget diventa mai notevolmente obsoleto.
Poiché come-frequente-è-troppo-frequente è una di quelle frustranti domande soggettive in cui non esiste una risposta "giusta", può aiutare a ottenere una seconda opinione organizzando alcuni test degli utenti. È anche possibile impostare alcuni test A / B per verificare se alcune frequenze di aggiornamento vengono ricevute in modo più positivo di altre.
Apri i tuoi progetti AppWidgetProviderInfo file (res / xml / new_app_widget_info.xml) e vedrai che definisce già un intervallo di aggiornamento predefinito di 86400000 millisecondi (24 ore).
Android: updatePeriodMillis = "86400000"
Ci sono un sacco di widget che si aggiornano solo una volta ogni 24 ore, ad esempio un widget che mostra le previsioni del tempo potrebbe dover solo recuperare nuove informazioni una volta al giorno. Tuttavia, anche se il tuo widget deve essere aggiornato solo una volta al giorno, questo non è l'ideale per testare la tua app. Nessuno vuole aspettare 24 ore solo per vedere se loro onUpdate ()
il metodo si sta attivando correttamente, quindi in genere utilizzerai l'intervallo più breve possibile quando esegui il test iniziale e poi cambi questo valore in seguito, se necessario.
Per semplificare il test della nostra app, utilizzerò l'intervallo più breve possibile:
Android: updatePeriodMillis = "1800000"
Il onUpdate ()
il metodo è responsabile dell'aggiornamento dei tuoi widget Visualizzazioni
con nuove informazioni. Se si apre il provider di widget del progetto (java / valori / NewAppWidget.java) allora vedrai che contiene già il contorno di un onUpdate ()
metodo:
@Override public void onUpdate (Contesto contesto, AppWidgetManager appManager, int [] appWidgetIds) // Potrebbero esserci più widget attivi, quindi aggiornarli tutti // for (int appWidgetId: appWidgetIds) updateAppWidget (contesto, appWidgetManager, appWidgetId) ;
Indipendentemente dal fatto che il widget venga aggiornato automaticamente o in risposta all'interazione dell'utente, il processo di aggiornamento è esattamente lo stesso: il gestore widget invia un tentativo di trasmissione con il ACTION_APPWIDGET_UPDATE
azione, e la classe del provider di widget risponde chiamando il onUpdate ()
metodo, che a sua volta chiama il updateAppWidget ()
metodo di supporto.
Una volta aggiornato il nostro NewAppWidget.java classe per recuperare e visualizzare l'ora corrente, il nostro progetto utilizzerà questa stessa sezione di codice indipendentemente da come onUpdate ()
il metodo è attivato:
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; importare android.content.Context; importare android.widget.RemoteViews; importare android.app.PendingIntent; import android.content.Intent; import android.net.Uri; importare java.text.DateFormat; import java.util.Date; public class NewAppWidget estende AppWidgetProvider static void updateAppWidget (Contesto contesto, AppWidgetManager appManager, int appWidgetId) // Recupera l'ora // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (new Date ()); // Costruisce l'oggetto RemoteViews // Viste RemoteViews = new RemoteViews (context.getPackageName (), R.layout.new_app_widget); views.setTextViewText (R.id.id_value, String.valueOf (appWidgetId)); // Recupera e visualizza l'ora // views.setTextViewText (R.id.update_value, context.getResources (). GetString (R.string.time, timeString)); Intento intento = nuovo intento (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivity (context, 0, intent, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); appWidgetManager.updateAppWidget (appWidgetId, viste); @Override public void onUpdate (Contesto contesto, AppWidgetManager appManager, int [] appWidgetIds) // Se sono attivi più widget, quindi aggiornarli tutti // per (int appWidgetId: appWidgetIds) updateAppWidget (contesto, appWidgetManager, appWidgetId);
C'è un problema con il codice precedente: se l'utente tocca il TextView
più volte nell'arco di un minuto, non ci sarà alcuna indicazione visiva che il widget è stato aggiornato, semplicemente perché non c'è un nuovo orario da visualizzare. Questo probabilmente non causerà problemi ai tuoi utenti finali, che difficilmente siederanno lì, toccando il TextView
più volte al minuto e chiedendosi perché il tempo non è cambiato. Tuttavia, questo potrebbe essere un problema durante il test della tua app, in quanto significa che dovrai attendere almeno 60 secondi tra l'attivazione del onUpdate ()
metodo.
Per garantire c'è sempre qualche tipo di conferma visuale che il onUpdate ()
il metodo è stato eseguito correttamente, visualizzerò un brindisi ogni volta onUpdate ()
è chiamato:
import android.widget.Toast; ... @Override public void onUpdate (Contesto contesto, appWidgetManager appManager, int [] appWidgetIds) for (int appWidgetId: appWidgetIds) updateAppWidget (contesto, appWidgetManager, appWidgetId); Toast.makeText (contesto, "Widget è stato aggiornato!", Toast.LENGTH_SHORT) .show ();
Il nostro widget verrà aggiornato automaticamente ogni mezz'ora, ma per quanto riguarda l'aggiornamento in risposta all'interazione dell'utente?
Abbiamo già gettato molte delle basi aggiungendo un Tocca per aggiornare TextView
al nostro layout e all'espansione del NewAppWidget.java classe per recuperare e visualizzare l'ora corrente ogni volta onUpdate ()
è chiamato.
L'unica cosa che rimane da fare è creare un Intento
con AppWidgetManager.ACTION_APPWIDGET_UPDATE
, che è un'azione che informa il widget che è il momento di aggiornare e quindi chiama questo intento in risposta all'utente che interagisce con il Tocca per aggiornare TextView
.
Ecco il completato NewAppWidget.java classe:
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; importare android.content.Context; importare android.widget.RemoteViews; importare android.app.PendingIntent; import android.content.Intent; import android.net.Uri; importare java.text.DateFormat; import java.util.Date; importare android.widget.Toast; public class NewAppWidget estende AppWidgetProvider static void updateAppWidget (contesto contesto, appWidgetManagerWidgetManager, int appWidgetId) // Recupera l'ora corrente // String timeString = DateFormat.getTimeInstance (DateFormat.SHORT) .format (new Date ()); Viste RemoteViews = nuove 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 un intent con l'azione AppWidgetManager.ACTION_APPWIDGET_UPDATE // Intento intentUpdate = new Intent (context, NewAppWidget.class); intentUpdate.setAction (AppWidgetManager.ACTION_APPWIDGET_UPDATE); // Aggiorna solo l'istanza del widget corrente, creando una matrice che contiene l'ID univoco del widget // int [] idArray = new int [] appWidgetId; intentUpdate.putExtra (AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray); // Avvolge l'intento come PendingIntent, utilizzando PendingIntent.getBroadcast () // PendingIntent pendingUpdate = PendingIntent.getBroadcast (context, appWidgetId, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT); // Invia l'intento in sospeso in risposta all'utente toccando il pulsante 'Aggiorna' TextView // views.setOnClickPendingIntent (R.id.update, pendingUpdate); Intento intento = nuovo intento (Intent.ACTION_VIEW, Uri.parse ("https://code.tutsplus.com/")); PendingIntent pendingIntent = PendingIntent.getActivity (context, 0, intent, 0); views.setOnClickPendingIntent (R.id.launch_url, pendingIntent); // Richiedere che AppWidgetManager aggiorni il widget dell'applicazione // appWidgetManager.updateAppWidget (appWidgetId, viste); @Override public void onUpdate (Contesto contesto, appWidgetManager AppManager, int [] appWidgetIds) for (int appWidgetId: appWidgetIds) updateAppWidget (contesto, appWidgetManager, appWidgetId); Toast.makeText (contesto, "Widget è stato aggiornato!", Toast.LENGTH_SHORT) .show ();
Essere in grado di aggiornare un widget su richiesta può essere inestimabile quando si esegue il test del progetto, poiché significa che non dovrai mai attendere l'intervallo di aggiornamento. Anche se non includi questa funzionalità nella tua applicazione finita, potresti voler aggiungere un temporaneo Tocca per aggiornare pulsante, solo per semplificarti la vita durante la prova del tuo progetto.
Il nostro widget ora sembra completamente diverso dal widget che Android Studio ha generato automaticamente per noi, ma al momento utilizza ancora l'immagine di anteprima generata automaticamente.
Idealmente, l'immagine di anteprima dovrebbe incoraggiare gli utenti a selezionare il widget dal Widget Picker, ma per lo meno dovrebbe essere una rappresentazione accurata di come il tuo widget effettivamente appare! Attualmente, i nostri tick di anteprima immagine né di quelle scatole, quindi abbiamo bisogno di crearne una nuova.
Il metodo più semplice è usare il Anteprima del widget applicazione inclusa nell'emulatore Android.
Creazione di un'anteprima del widget
Innanzitutto, installa il tuo progetto su un dispositivo virtuale Android (AVD). Quindi apri il cassetto delle app dell'AVD e avvia l'applicazione Anteprima widget. L'AVD visualizzerà un elenco di tutte le app installate sul dispositivo: selezionare l'app dall'elenco.
Il tuo widget verrà visualizzato su uno sfondo vuoto. Dedica un po 'di tempo a ridimensionare e modificare il tuo widget in modo che appaia al meglio e, una volta soddisfatti dei risultati, seleziona Scatta un'istantanea. Lo screenshot verrà salvato come PNG negli AVD Scaricare cartella. Per recuperare questo file, torna a Android Studio e apri il Device File Explorer, selezionando Visualizza> Finestre degli strumenti> Esplora file di dispositivo dalla barra degli strumenti. Nella vista Esplora file dispositivo, vai a sdcard / download cartella, dove troverai l'immagine di anteprima salvata come: [App_name] _ori_ [orientamento] .png
Trascina questa immagine fuori da Android Studio e rilasciala da qualche parte facilmente accessibile, come il tuo desktop. Assegna all'immagine un nome più descrittivo, quindi trascina l'immagine nei progetti drawable cartella. Ora puoi aprire il AppWidgetProviderInfo file (in questo caso, questo è new_app_widget_info.xml) e cambia la riga seguente per fare riferimento alla tua nuova immagine di anteprima:
Android: previewImage = "@ drawable / example_appwidget_preview"
Infine, è possibile rimuovere il non necessario example_appwidget_preview disegnabile dal tuo progetto.
È ora di mettere alla prova il widget finito!
Innanzitutto, installa il progetto aggiornato sul tuo dispositivo fisico Android o AVD. Rimuovi tutte le istanze esistenti di questo widget dal tuo homescreen, così tu conoscere stai lavorando con l'ultima versione.
Per aggiungere il widget, premere qualsiasi spazio vuoto sulla schermata iniziale, toccare widget e quindi seleziona il tuo widget. Avrai la possibilità di ridimensionare e riposizionare il widget, se necessario.
Il Ultimo aggiornamento valore mostrerà l'ora in cui hai creato questo widget. stampa Tocca per aggiornare e il widget dovrebbe mostrare un brindisi e una nuova ora. Se si posiziona una seconda istanza del widget sul tuo homescreen, dovrebbe visualizzare un orario diverso dal primo.
È possibile aggiornare una di queste istanze del widget dando il suo Tocca per aggiornare TextView
un rubinetto. Se si attiva un aggiornamento manuale per il primo widget, il secondo widget non verrà aggiornato e viceversa.
Oltre agli aggiornamenti manuali, l'App Widget Manager si aggiornerà tutti istanze del tuo widget una volta ogni 30 minuti, in base all'ora in cui hai creato la prima istanza. Sebbene gli aggiornamenti manuali possano comportare istanze che visualizzano tempi diversi, una volta ogni mezz'ora tutte le istanze verranno aggiornate contemporaneamente, a quel punto visualizzeranno la stessa ora.
È possibile mantenere alcune istanze di questo widget sulla schermata iniziale, in modo da poter monitorare il modo in cui il loro contenuto cambia nel tempo in risposta a una combinazione di aggiornamenti automatici e manuali.
In questa serie, abbiamo creato un widget dell'applicazione Android che dimostra come implementare tutte le funzionalità più comuni presenti nei widget delle app. Se hai seguito sin dall'inizio, a questo punto avrai creato un widget che si aggiorna automaticamente e in risposta all'input dell'utente, e che è in grado di reagire agli eventi onClick (puoi anche scaricare il progetto completo da GitHub ).
Nel prossimo post, esamineremo alcune best practice per garantire che il widget fornisca una buona esperienza utente e come migliorare il widget con un'attività di configurazione.