image/svg+xml $ $ ing$ ing$ ces$ ces$ Res Res ea ea Res->ea ou ou Res->ou r r ea->r ch ch ea->ch r->ces$ r->ch ch->$ ch->ing$ T T T->ea ou->r

Présentation

Application widget

Principe de fonctionnement

Feuille de route pour créer un widget inter-applicatif

  1. Créer le layout XML du widget
    • Seuls certains layouts sont utilisables : FrameLayout, LinearLayout, RelativeLayout, GridLayout (ConstraintLayout non supporté)
    • Ne peut contenir que certaines vues compatibles avec RemoteView telles que TextView, Button, ImageView, ProgressBar (EditText par exemple n'est pas compatible)
  2. Créer un fichier XML de description des métadonnées du widget dans res/xml
  3. Créer le AppWidgetProvider pour programmer le comportement à adopter pour mettre à jour le widget ; le déclarer dans le manifeste associé aux actions gérées
  4. Provoquer depuis le code de l'application A des mises à jour du widget (en envoyant un Intent vers l'AppWidgetManager)
    1. Mise à jour des propriétés des composants graphiques
    2. Enregistrement/suppression de listeners liés à l'envoi d'Intent
  5. Les composants graphiques basés sur des adaptateurs tels que ListView ou GridView peuvent être employés en utilisant un RemoteViewFactory pour la mise à jour de l'adaptateur

Exemple : widget affichant le temps écoulé depuis le démarrage

Création du layout (simple) pour le widget :

<?xml version="1.0" encoding="utf-8"?>
<!-- Code sample from Coursand [http://igm.univ-mlv.fr/~chilowi/], under the Apache 2.0 License -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/elapsedTimeView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00FFFFFF"
        android:text="TextView" />
</LinearLayout>

Implantation du receiver réalisant la mise à jour du widget lorsqu'un événement de mise à jour est reçu :

// Code sample from Coursand [http://igm.univ-mlv.fr/~chilowi/], under the Apache 2.0 License

package fr.upem.coursand.elapsedtimewidget

import android.app.LauncherActivity
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.os.SystemClock
import android.widget.RemoteViews
import fr.upem.coursand.R

/** Implementation of an appwidget displaying the elapsed time since boot */
class ElapsedTimeAppWidgetProvider: AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each App Widget that belongs to this provider
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch the main activity of Coursand
            val pendingIntent: PendingIntent = Intent(context, LauncherActivity::class.java)
                    .let { PendingIntent.getActivity(context, 0, it, 0) }

            // Get the layout for the App Widget
            // Update the elapsed time of the TextView and a click listener on it launching
            // the main activity of coursand
            val views: RemoteViews = RemoteViews(context.packageName, R.layout.widget_elapsedtime).apply {
                val elapsedMinutes = SystemClock.elapsedRealtime() / 1000 / 60 // in minutes
                this.setTextViewText(R.id.elapsedTimeView, "$elapsedMinutes minutes since boot")
                setOnClickPendingIntent(R.id.elapsedTimeView, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current app widget
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Ecriture du fichier res/xml/elapsedtime_appwidget_info.xml d'informations sur le widget :

<!-- Code sample from Coursand [http://igm.univ-mlv.fr/~chilowi/], under the Apache 2.0 License -->

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:updatePeriodMillis="60000"
    android:previewImage="@drawable/ic_menu"
    android:initialLayout="@layout/widget_elapsedtime"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen">
</appwidget-provider>

Déclaration dans la manifeste du widget :

<manifest ...>
	...
	<application>
		...
		<receiver android:name=".elapsedtimewidget.ElapsedTimeAppWidgetProvider" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/elapsedtime_appwidget_info" />
        </receiver>
	</application>
</manifest>