Suivre les métriques de votre widget

Android 16 inclut des API de métriques supplémentaires plus précises. Ces métriques permettent de suivre les actions d'appui, telles que le clic sur un bouton, le défilement, les impressions, ainsi que la taille et la position du widget.

L'API principale est AppWidgetEvent. Utilisez WorkManager pour créer un worker périodique qui capture l'engagement du widget, que ce soit quotidiennement, chaque semaine ou chaque fois que votre application est ouverte.

Consultez l'extrait suivant pour obtenir un exemple de suivi des clics, des défilements et de la durée d'impression.

@RequiresApi(Build.VERSION_CODES_FULL.BAKLAVA_1)
fun getWidgetEngagementMetrics(context: Context) {
    val manager = AppWidgetManager.getInstance(context)

    val endTime = System.currentTimeMillis()
    val startTime = endTime - (24 * 60 * 60 * 1000) // a day ago

    val events = manager.queryAppWidgetEvents(startTime, endTime)

    if (events.isEmpty()) {
        Log.d(TAG, "No events found for the given time range.")
    }

    val metrics = hashMapOf(
        "clicks" to 0L,
        "scrolls" to 0L,
        "totalImpressionLength" to 0L
    )

    for (event in events) {

        Log.d(TAG, "Event Start: ${event.start}")
        Log.d(TAG, "Event End: ${event.end}")

        val widgetId = event.appWidgetId

        // Tap actions
        val clickedIds = event.clickedIds
        if (clickedIds?.isNotEmpty() == true) {
            metrics["clicks"] = metrics.getValue("clicks") + clickedIds.size
            // Log or analyze which components were clicked.
            for (id in clickedIds) {
                Log.d(TAG, "Widget $widgetId: Tap event on component with ID $id")
            }
        }

        // Scroll events
        val scrolledIds = event.scrolledIds
        if (scrolledIds?.isNotEmpty() == true) {
            metrics["scrolls"] = metrics.getValue("scrolls") + scrolledIds.size
            // Log or analyze which lists were scrolled.
            for (id in scrolledIds) {
                Log.d(TAG, "Widget $widgetId: Scroll event in list with ID/tag $id")
            }
        }

        // Impressions
        metrics["totalImpressionLength"] = metrics.getValue("totalImpressionLength") + event.visibleDuration.toMillis()
        Log.d(
            TAG,
            "Widget $widgetId: Impression event with duration " + event.visibleDuration.toMillis() + "ms"
        )

        // Position
        val position = event.position
        if (position != null) {
            Log.d(
                TAG,
                "Widget $widgetId: left=${position.left}, right=${position.right}, top=${position.top}, bottom=${position.bottom}"
            )
        }
    }
    Log.d("WidgetMetrics", "Metrics: $metrics")
}

Pour préserver l'état du système, les événements sont signalés une fois par heure par défaut, bien que les fabricants d'appareils puissent modifier la période de référence. Par exemple, sur les appareils Pixel, si un utilisateur fait défiler la même liste dans votre widget 10 fois en une heure, un seul événement de défilement sera comptabilisé pour cette heure.

Pour les tests, vous pouvez définir l'attribut suivant sur une heure spécifiée et redémarrer votre appareil de test. Dans l'exemple suivant, la fenêtre de rapport est définie sur 0 ms et les événements sont signalés immédiatement.

adb shell device_config override systemui widget_events_report_interval_ms 0

Pour définir un tag personnalisé pour les rapports sur les clics et les défilements, vous pouvez utiliser RemoteViews.setAppWidgetEventTag sur une vue de votre mise en page RemoteViews. Ce tag entier est utilisé lorsque vous interrogez des AppWidgetEvents qui incluent des clics ou des défilements sur cette vue.