Suivre les métriques de votre widget

Android 16 inclut des API de métriques supplémentaires plus précises. Ces métriques suivent les actions tactiles telles que les clics 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 des widgets une fois par heure.

Voici un exemple de snippet permettant de suivre les clics, les défilements et 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, mais les fabricants d'appareils peuvent modifier la période de signalement. 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écifique et redémarrer votre appareil de test. Dans l'exemple suivant, la fenêtre de signalement 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 clics et les défilements, vous pouvez utiliser RemoteViews.setAppWidgetEventTag sur une vue dans votre mise en page RemoteViews. Ce tag entier est utilisé lorsque vous interrogez AppWidgetEvents qui incluent des clics ou des défilements sur cette vue.