public class

AnalyticsParser

extends java.lang.Object

 java.lang.Object

↳androidx.car.app.mediaextensions.analytics.client.AnalyticsParser

Gradle dependencies

compile group: 'androidx.car.app', name: 'app', version: '1.7.0-beta01'

  • groupId: androidx.car.app
  • artifactId: app
  • version: 1.7.0-beta01

Artifact androidx.car.app:app:1.7.0-beta01 it located at Google repository (https://maven.google.com/)

Overview

Provides tools to parse AnalyticEvents from Bundle.

Summary

Methods
public static booleanisAnalyticsAction(java.lang.String action)

Checks if supplied action is an Analytics action.

public static voidparseAnalyticsAction(java.lang.String action, Bundle extras, AnalyticsCallback analyticsCallback)

Parses a batch of AnalyticsEvents from a custom action and extras.

public static voidparseAnalyticsAction(java.lang.String action, Bundle extras, java.util.concurrent.Executor executor, AnalyticsCallback analyticsCallback)

Parses a batch of AnalyticsEvents from a custom action and extras.

public static voidparseAnalyticsBundle(Bundle analyticsBundle, java.util.concurrent.Executor executor, AnalyticsCallback analyticsCallback)

Helper method to deserialize analytics event bundles marshalled through an intent bundle.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public static boolean isAnalyticsAction(java.lang.String action)

Checks if supplied action is an Analytics action.

Parameters:

action: custom action

Returns:

boolean value whether the action is an analytics action.

public static void parseAnalyticsAction(java.lang.String action, Bundle extras, AnalyticsCallback analyticsCallback)

Parses a batch of AnalyticsEvents from a custom action and extras.

Deserializes each event in batch and sends to analyticsCallback.

Usage: Pass in action string and extras bundle to this method from MediaBrowserServiceCompat.onCustomAction(String, Bundle, MediaBrowserServiceCompat.Result). If present, the batch of analytic events will be parsed, deserialized and passed to the supplied AnalyticsCallback.

Parameters:

action: custom action
extras: custom action extras.
analyticsCallback: callback for deserialized events.

public static void parseAnalyticsAction(java.lang.String action, Bundle extras, java.util.concurrent.Executor executor, AnalyticsCallback analyticsCallback)

Parses a batch of AnalyticsEvents from a custom action and extras.

Deserializes each event in batch and sends to analyticsCallback.

Usage: Pass in action string and extras bundle to this method from MediaBrowserServiceCompat.onCustomAction(String, Bundle, MediaBrowserServiceCompat.Result). If present, the batch of analytic events will be parsed, deserialized and passed to the supplied AnalyticsCallback.

Parameters:

action: custom action
extras: custom action extras.
executor: Valid Executor on which callback will be called.
analyticsCallback: callback for deserialized events.

public static void parseAnalyticsBundle(Bundle analyticsBundle, java.util.concurrent.Executor executor, AnalyticsCallback analyticsCallback)

Helper method to deserialize analytics event bundles marshalled through an intent bundle.

Parameters:

analyticsBundle: Bundle with serialized analytics event
analyticsCallback: Callback for deserialized analytics object.

Source

/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.car.app.mediaextensions.analytics.client;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_BROWSE_NODE_CHANGE;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_BUNDLE_ARRAY_KEY;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_DATA_KEY_EVENT_NAME;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_MEDIA_CLICKED;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_VIEW_CHANGE;
import static androidx.car.app.mediaextensions.analytics.Constants.ANALYTICS_EVENT_VISIBLE_ITEMS;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.car.app.annotations.ExperimentalCarApi;
import androidx.car.app.mediaextensions.analytics.Constants;
import androidx.car.app.mediaextensions.analytics.ThreadUtils;
import androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent;
import androidx.car.app.mediaextensions.analytics.event.BrowseChangeEvent;
import androidx.car.app.mediaextensions.analytics.event.ErrorEvent;
import androidx.car.app.mediaextensions.analytics.event.MediaClickedEvent;
import androidx.car.app.mediaextensions.analytics.event.ViewChangeEvent;
import androidx.car.app.mediaextensions.analytics.event.VisibleItemsEvent;
import androidx.media.MediaBrowserServiceCompat;

import java.util.ArrayList;
import java.util.concurrent.Executor;

/** Provides tools to parse AnalyticEvents from Bundle. **/
@ExperimentalCarApi
@RestrictTo(LIBRARY)
public class AnalyticsParser {
    private static final String TAG = "AnalyticsParser";

    private AnalyticsParser() {}

    /**
     *
     * Checks if supplied action is an Analytics action.
     *
     * @param action custom action
     * @return boolean value whether the action is an analytics action.
     */
    public static boolean isAnalyticsAction(@NonNull String action) {
        return Constants.ACTION_ANALYTICS.equalsIgnoreCase(action);
    }

    /**
     * Parses a batch of {@link AnalyticsEvent}s from a custom action and extras.
     * <p>
     *  Deserializes each event in batch and sends to analyticsCallback.
     * <p>
     *
     * <p>
     *     Usage: Pass in action string and extras bundle to this method from
     *     {@link androidx.media.MediaBrowserServiceCompat#onCustomAction(String, Bundle,
     *     MediaBrowserServiceCompat.Result)}.
     *     If present, the batch of analytic events will be parsed, deserialized and passed to the
     *     supplied {@link AnalyticsCallback}.
     * </p>
     *
     * @param action custom action
     * @param extras custom action extras.
     * @param analyticsCallback callback for deserialized events.
     */
    public static void parseAnalyticsAction(@NonNull String action, @Nullable Bundle extras,
            @NonNull AnalyticsCallback analyticsCallback) {
        parseAnalyticsAction(action, extras, ThreadUtils.getMainThreadExecutor(),
                analyticsCallback);
    }

    /**
     * Parses a batch of {@link AnalyticsEvent}s from a custom action and extras.
     * <p>
     *  Deserializes each event in batch and sends to analyticsCallback.
     * <p>
     *
     * <p>
     *     Usage: Pass in action string and extras bundle to this method from
     *     {@link
     *     androidx.media.MediaBrowserServiceCompat#onCustomAction(String, Bundle,
     *     MediaBrowserServiceCompat.Result)}.
     *     If present, the batch of analytic events will be parsed, deserialized and passed to the
     *     supplied {@link AnalyticsCallback}.
     * </p>
     *
     * @param action custom action
     * @param extras custom action extras.
     * @param executor Valid Executor on which callback will be called.
     * @param analyticsCallback callback for deserialized events.
     */
    @SuppressWarnings("deprecation")
    public static void parseAnalyticsAction(@NonNull String action, @Nullable Bundle extras,
            @NonNull Executor executor, @NonNull AnalyticsCallback analyticsCallback) {

        if (!action.equals(Constants.ACTION_ANALYTICS)) {
            analyticsCallback.onErrorEvent(new ErrorEvent(new Bundle(),
                    ErrorEvent.ERROR_CODE_INVALID_EVENT));
            return;
        }

        if (extras == null || extras.isEmpty()) {
            Log.e(TAG, "Analytics event bundle is null or empty.");
            analyticsCallback.onErrorEvent(new ErrorEvent(new Bundle(),
                    ErrorEvent.ERROR_CODE_INVALID_EXTRAS));
            return;
        }

        ArrayList<Bundle> eventBundles =
                extras.getParcelableArrayList(ANALYTICS_EVENT_BUNDLE_ARRAY_KEY);

        if (eventBundles == null || eventBundles.isEmpty()) {
            Log.e(TAG, "Analytics event bundle list is empty.");
            analyticsCallback.onErrorEvent(new ErrorEvent(new Bundle(),
                    ErrorEvent.ERROR_CODE_INVALID_BUNDLE));
            return;
        }

        for (Bundle bundle : eventBundles) {
            // TODO(b/322512398): Handle version mismatch
            AnalyticsParser.parseAnalyticsBundle(bundle, executor, analyticsCallback);
        }
    }

    /**
     * Helper method to deserialize analytics event bundles marshalled through an intent bundle.
     * <p>
     * @param analyticsBundle Bundle with serialized analytics event
     * @param analyticsCallback Callback for deserialized analytics object.
     */
    public static void parseAnalyticsBundle(@NonNull Bundle analyticsBundle,
            @NonNull Executor executor, @NonNull AnalyticsCallback analyticsCallback) {
        String eventName = analyticsBundle.getString(ANALYTICS_EVENT_DATA_KEY_EVENT_NAME, "");

        if (TextUtils.isEmpty(eventName)) {
            executor.execute(() -> analyticsCallback.onErrorEvent(new ErrorEvent(analyticsBundle,
                    ErrorEvent.ERROR_CODE_INVALID_EVENT)));
            return;
        }

        executor.execute(() -> createEvent(analyticsCallback, getEventType(eventName),
                analyticsBundle));
    }

    private static void createEvent(
            @NonNull AnalyticsCallback analyticsCallback,
            @AnalyticsEvent.EventType int eventType,
            Bundle analyticsBundle) {

        switch (eventType) {
            case AnalyticsEvent.EVENT_TYPE_VISIBLE_ITEMS_EVENT:
                analyticsCallback.onVisibleItemsEvent(new VisibleItemsEvent(analyticsBundle));
                break;
            case AnalyticsEvent.EVENT_TYPE_MEDIA_CLICKED_EVENT:
                analyticsCallback.onMediaClickedEvent(new MediaClickedEvent(analyticsBundle));
                break;
            case AnalyticsEvent.EVENT_TYPE_BROWSE_NODE_CHANGED_EVENT:
                analyticsCallback.onBrowseNodeChangeEvent(new BrowseChangeEvent(analyticsBundle));
                break;
            case AnalyticsEvent.EVENT_TYPE_VIEW_CHANGE_EVENT:
                analyticsCallback.onViewChangeEvent(new ViewChangeEvent(analyticsBundle));
                break;
            default:
                analyticsCallback.onUnknownEvent(analyticsBundle);
                break;
        }
    }

    @AnalyticsEvent.EventType
    private static int getEventType(String eventName) {
        switch (eventName) {
            case ANALYTICS_EVENT_MEDIA_CLICKED:
                return AnalyticsEvent.EVENT_TYPE_MEDIA_CLICKED_EVENT;
            case ANALYTICS_EVENT_BROWSE_NODE_CHANGE:
                return AnalyticsEvent.EVENT_TYPE_BROWSE_NODE_CHANGED_EVENT;
            case ANALYTICS_EVENT_VIEW_CHANGE:
                return AnalyticsEvent.EVENT_TYPE_VIEW_CHANGE_EVENT;
            case ANALYTICS_EVENT_VISIBLE_ITEMS:
                return AnalyticsEvent.EVENT_TYPE_VISIBLE_ITEMS_EVENT;
            default:
                return AnalyticsEvent.EVENT_TYPE_UNKNOWN_EVENT;
        }
    }
}