Track metrics for your widget

Android 16 includes additional metrics APIs that are more granular. These metrics track tap actions such as a button click, scroll, impressions, and the widget's size and position.

The main API is AppWidgetEvent. Use WorkManager to create a periodic worker that captures widget engagement once an hour.

See the following snippet for an example of tracking clicks, scrolls and impression length.

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

To preserve system health, events are reported once an hour by default although device manufacturers may change the reporting window. For example, on Pixel devices if a user scrolls the same list in your widget 10 times in an hour, only 1 scroll event will be counted for that hour.

For testing, you can set the following attribute to a specified time and restart your test device. In the following example, the report window is set to 0 ms and events are reported immediately.

adb shell device_config override systemui widget_events_report_interval_ms 0 

In order to set a custom tag for reporting clicks and scrolls, you can use RemoteViews.setAppWidgetEventTag on a view within your RemoteViews layout. This integer tag is used when you query for AppWidgetEvents that include clicks or scrolls on this view.