מעקב אחר מדדים בווידג'ט

‫Android 16 כולל ממשקי API נוספים למדדים, שהם מפורטים יותר. המדדים האלה עוקבים אחרי פעולות הקשה כמו קליק על כפתור, גלילה, חשיפות, והגודל והמיקום של הווידג'ט.

ה-API הראשי הוא AppWidgetEvent. משתמשים ב-WorkManager כדי ליצור worker תקופתי שמתעד את האינטראקציה עם הווידג'ט, מדי יום, מדי שבוע או בכל פעם שהאפליקציה נפתחת.

בקטע הקוד הבא מוצגת דוגמה למעקב אחרי קליקים, גלילות ומשך החשיפה.

@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 פעמים בשעה, רק אירוע גלילה אחד ייספר באותה שעה.

למטרות בדיקה, אפשר להגדיר את המאפיין הבא לזמן מסוים ולהפעיל מחדש את מכשיר הבדיקה. בדוגמה הבאה, חלון הדיווח מוגדר ל-0 אלפיות השנייה והאירועים מדווחים באופן מיידי.

adb shell device_config override systemui widget_events_report_interval_ms 0

כדי להגדיר תג מותאם אישית לדיווח על קליקים וגלילות, אתם יכולים להשתמש ב-RemoteViews.setAppWidgetEventTag בתצוגה בפריסה של RemoteViews. תג המספר השלם הזה משמש כששולחים שאילתה לגבי AppWidgetEvents שכוללים קליקים או גלילות בתצוגה הזו.