A volte, sulla home di un dispositivo Android (la schermata che appare quando non sono aperte app), notiamo piccoli riquadri che forniscono informazioni o contengono comandi che attivano funzionalità: gli App Widget. In questa lezione impareremo a crearli e integrarli in un progetto Android Studio.

Uso degli App Widget
Per chi non fosse avvezzo a questi componenti (da un punto di vista dell'utente), ricordiamo come integrarli nella home. Esercitando una pressione prolungata sullo sfondo, appare un menu con cui si accede alla schermata di gestione dei Widget.
Da qui si può scegliere il widget da inserire nella Home del dispositivo.

La loro creazione in un progetto Android Studio richiede un certo numero di passi, che andiamo ad illustrare nel paragrafo seguente.
Progettare Widget
L'esempio che mostriamo crea un Widget dotato di due pulsanti che lanciano Intent in grado di attivare la fotocamera in modalità video o fotografica.
Il primo passo consiste nel realizzare un layout RemoteViews far uso solo delle seguenti View
-
FrameLayout
LinearLayout
RelativeLayout
GridLayout
layout- tra gli altri controlli
Button
ImageButton
ImageView
TextView
ListView
GridView
AnalogClock
Chronometer
ProgressBar
ViewFlipper
StackView
AdapterViewFlipper
Questo il layout del nostro esempio (file res/layout/camera_widget.xml):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="#ff8533"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Scatta video o foto da qui"
android:textStyle="bold"
android:padding="8dp"
android:textSize="18sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<ImageButton
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="-"
android:background="#44ff8533"
android:padding="8dp"
android:src="@drawable/ic_movie_creation_black_24dp"
android:id="@+id/btn_video"/>
<ImageButton
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#44ff8533"
android:src="@drawable/ic_add_a_photo_black_24dp"
android:id="@+id/btn_photo"
android:padding="8dp"/>
</LinearLayout>
</LinearLayout>
Successivamente, dobbiamo creare una classe Java che estende AppWidgetProvider
ApplicationManifest.xml
<application>
<receiver android:name=".CameraWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/camera_widget_info" />
</receiver>
dove l'attributo name
specifica la classe di implementazione dell'App Widget, il blocco intent-filter
sancisce l'evento che lo "sveglierà" in quanto estensione di un BroadcastReceiver, mentre l'altro blocco interno di tipo meta-data
specifica il file di configurazione che troveremo tra le risorse di tipo XML.
Il file di configurazione camera_widget_info del nostro esempio è il seguente:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/camera_widget"
android:initialLayout="@layout/camera_widget"
android:minHeight="40dp"
android:minWidth="180dp"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="1800000"
android:previewImage="@drawable/screenshot"
android:widgetCategory="home_screen"/>
In esso, troviamo specificate dimensioni minime, direzioni di espansione manuale del widget nonchè l'immagine di anteprima che apparirà nel gestore degli App Widget. È presente anche l'attributo updatePeriodMillis
Quello che segue è il codice della classe CameraWidget:
public class CameraWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
// (1) carica layout nella RemoteViews
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.camera_widget);
// (2.1) gestione click su pulsante che attiva video
Intent videoIntent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
PendingIntent pendingIntent = PendingIntent.getActivity (context, 0,
videoIntent, 0);
views.setOnClickPendingIntent (R.id.btn_video, pendingIntent);
// (2.2) gestione click su pulsante che attiva foto
Intent photoIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
PendingIntent pendingIntentContact = PendingIntent.getActivity (context, 0,
photoIntent, 0);
views.setOnClickPendingIntent (R.id.btn_photo, pendingIntentContact);
// (3) AppWidgetManager assegna la RemoteViews all'App Widget con id appWidgetId
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
}
Il metodo onUpdate
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_RESTORED
Context
updateAppWidget
In updateAppWidget, aggiorneremo fisicamente il layout procedendo in questo modo:
- caricheremo il layout in una RemoteViews;
- gestiremo gli eventi legati ai pulsanti utilizzando dei PendingIntent che conterranno Intent e descrizione dell'evento che dovrà essere attivato alla loro pressione;
- tramite l'AppWidgetManager specificheremo che la RemoteViews così definita e configurata appartiene al widget che possiede uno specifico id.
Conclusioni
In questo esempio, abbiamo visto un semplice App Widget che permette di accedere ad applicazioni di sistema, quindi svincolate dal progetto Android in cui è stato definito. Ciò può essere molto utile ma si possono avere vantaggi ancora maggiori offrendoli come accesso rapido ai contenuti della nostra app: approfondimenti in materia possono essere ottenuti dalla documentazione ufficiale.