跟踪 widget 的指标

Android 16 包含更精细的其他 Metrics API。这些指标会跟踪点按操作,例如按钮点击、滚动、展示以及 widget 的大小和位置。

主要 API 为 AppWidgetEvent。使用 WorkManager 创建一个定期工作器,用于捕获微件互动情况,无论是每天、每周还是每次打开应用时。

请参阅以下代码段,了解如何跟踪点击、滚动和展示时长。

@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")
}

为维护系统健康,默认情况下,事件每小时报告一次,但设备制造商可以更改报告时间范围。例如,在 Pixel 设备上,如果用户在一小时内滚动微件中的同一列表 10 次,则该小时内只会统计 1 次滚动事件。

为了进行测试,您可以将以下属性设置为指定时间,然后重启测试设备。在以下示例中,报告窗口设置为 0 毫秒,事件会立即报告。

adb shell device_config override systemui widget_events_report_interval_ms 0

如需为报告点击和滚动设置自定义标记,您可以在 RemoteViews 布局中的视图上使用 RemoteViews.setAppWidgetEventTag。当您查询包含此视图上的点击或滚动操作的 AppWidgetEvents 时,系统会使用此整数标记。