Analytics Android Collector
This guide describes how to set up the Android Collector v3. You can find a guide for the deprecated v2 collector here.
How to set up Analytics on Android
Bitmovin Analytics enables you to get useful insights into the video experience in your apps. The Bitmovin Player for Android includes Analytics pre-integrated. Players like ExoPlayer, Media3 ExoPlayer, and the Amazon IVS player can be tracked through our player-specific collectors.
In order to complete this guide, you need at least a basic setup of your chosen player. If you haven't set up your Player yet, go to the corresponding Player documentation page first: Bitmovin Player getting started guide, ExoPlayer documentation, Media3 ExoPlayer documentation, Amazon IVS Player documentation.
You also need to set up your analytics license and allowlist your domain. If you haven't done this yet, go to our How to Set Up page and follow the steps there.
Platform requirements:
Collector | Supported Android Version |
---|---|
Bitmovin Player Collector | Android 5+ |
ExoPlayer Collector | Android 5+ |
Media3 ExoPlayer Collector | Android 5+ |
Amazon IVS Player Collector | Android 5+ |
Bitmovin Player
Step 1: Configure Analytics
Starting with version 3.41.0
of the player, Analytics comes pre-integrated in the player. You just need to enable Analytics during creation of the Player.
Enable Analytics for the Player
For a minimal setup, only the license key needs to be specified. For more analytics configuration see here.
This minimal setup is enough to enable basic tracking.
val playerConfig = PlayerConfig()
val analyticsConfig = AnalyticsConfig(licenseKey = "<ANALYTICS_LICENSE_KEY>")
val player = Player(context, playerConfig, AnalyticsPlayerConfig.Enabled(analyticsConfig))
Enrich analytics data with Metadata
In order to enrich analytics with more data, DefaultMetadata
and SourceMetadata
can be set.
DefaultMetadata
can be set during player creation, and this contains source independent data.
val defaultMetadata = DefaultMetadata(
customUserId = "userId",
customData = CustomData(customData1 = "appVersion4")
)
val player = Player(
context,
playerConfig,
AnalyticsPlayerConfig.Enabled(analyticsConfig, defaultMetadata),
)
SourceMetadata
can be set for each source to add more source-specific metadata.
val sourceMetadata = SourceMetadata(
title = "stream title",
videoId = "exampleId" ,
customData = CustomData(customData2 = "ExampleGenre")
)
val source = Source(sourceConfig, AnalyticsSourceConfig.Enabled(sourceMetadata))
player.load(source)
Step 2: Check Statistics in Dashboard
After the setup is done there's nothing more to do. Events are recorded automatically and you can head over to the Analytics Dashboard to see your metrics.
3rd Party Players
Step 1: Add the SDK to Your Project.
Add the Bitmovin release repository to your project
Add a link to our release repository to your application's build.gradle
file. In addition to that, the Google maven repository must be added.
allprojects {
repositories {
mavenCentral()
google()
maven {
url 'https://artifacts.bitmovin.com/artifactory/public-releases'
}
}
}
Add the Dependency to the Project
Add the Bitmovin Analytics Android SDK as a dependency to your main project's build.gradle
file as shown below, while replacing {Version Number}
with the desired SDK version number. The available SDK versions are listed in our Release Notes. We recommend to always stay up to date with both player and collector versions. However if you are using an older player version, check out which collector version you should use at our Android Collector Github page.
dependencies {
implementation 'com.bitmovin.analytics:collector-media3-exoplayer:{Version Number}'
}
dependencies {
implementation 'com.bitmovin.analytics:collector-exoplayer:{Version Number}'
}
dependencies {
implementation 'com.bitmovin.analytics:collector-amazon-ivs:{Version Number}'
}
Step 2: Setup the Collector
First create a basic AnalyticsConfig
object with your Analytics License key. You can further customise it by adding optional configuration parameters. For more information and a complete list of configuration fields see our Configuration Guide.
Please replace ANALYTICS_LICENSE_KEY
with a license key from your account. Please checkout How to set up to learn more about how to get to your analytics license.
Create the collector object by passing the config object. Finally attach your player to the collector. Always detach your player from the collector once you are done, e.g. when calling the player.release()
method.
// Create a AnalyticsConfig using your Bitmovin analytics license key
val analyticsConfig = AnalyticsConfig("<ANALYTICS_LICENSE_KEY>")
// Create Analytics Collector for Media3 ExoPlayer
val analyticsCollector = IMedia3ExoPlayerCollector.Factory.create(applicationContext, analyticsConfig)
// create and set SourceMetadata
val sourceMetadata = SourceMetadata(title = "exampletitle", videoId = "exampleId")
analyticsCollector.sourceMetadata = sourceMetadata
// Attach your Media3 ExoPlayer instance
analyticsCollector.attachPlayer(player)
// set mediaItem and start playing video after attaching
player.setMediaItem(mediaItem)
player.prepare()
player.play()
// Detach your player when you are done.
// For example, call this method before releasing the player
analyticsCollector.detachPlayer()
// Create a AnalyticsConfig using your Bitmovin analytics license key
val analyticsConfig = AnalyticsConfig("<ANALYTICS_LICENSE_KEY>")
// Create Analytics Collector for ExoPlayer
val analyticsCollector = IExoPlayerCollector.Factory.create(applicationContext, analyticsConfig)
// create and set SourceMetadata
val sourceMetadata = SourceMetadata(title="exampletitle", videoId="exampleId")
analyticsCollector.sourceMetadata = sourceMetadata
// Attach your ExoPlayer instance
analyticsCollector.attachPlayer(player)
// set mediaItem and start playing video after attaching
player.setMediaItem(mediaItem)
player.prepare()
player.play()
// Detach your player when you are done.
// For example, call this method before releasing the player
analyticsCollector.detachPlayer()
// Create an AnalyticsConfig using your Bitmovin analytics license key
val analyticsConfig = AnalyticsConfig("<ANALYTICS_LICENSE_KEY>")
// Create Analytics Collector for Amazon IVS Player
val analyticsCollector = IAmazonIvsPlayerCollector.Factory.create(applicationContext, analyticsConfig)
// create and set SourceMetadata
val sourceMetadata = SourceMetadata(title="exampletitle", videoId="exampleId")
analyticsCollector.sourceMetadata = sourceMetadata
// Attach your Amazon IVS Player instance
analyticsCollector.attachPlayer(player)
// load and start playing video after attaching
player.load(sourceUri)
player.play()
// Detach your player when you are done.
// For example, call this method before releasing the player
analyticsCollector.detachPlayer()
When switching to a new video we recommend that you follow the sequence of events below.
// Detach the player when the first video is completed
analyticsCollector.detachPlayer()
// change SourceMetadata
val sourceMetadata2 = SourceMetadata(title = "exampletitle2", videoId = "exampleId2")
analyticsCollector.sourceMetadata = sourceMetadata2
// Reattach your player instance
analyticsCollector.attachPlayer(player)
player.setMediaItem(mediaItem2)
player.prepare()
player.play()
// Detach the player when the first video is completed
analyticsCollector.detachPlayer()
// change SourceMetadata
val sourceMetadata2 = SourceMetadata(title="exampletitle2", videoId="exampleId2")
analyticsCollector.sourceMetadata = sourceMetadata2
// Reattach your player instance
analyticsCollector.attachPlayer(player)
player.load(source2Uri)
player.play()
Step 3: Check Statistics in Dashboard
After the setup is done there is nothing more to do. Events are recorded automatically and you can head over to the Analytics Dashboard to see statistics.
Threading Model
The collector API is not thread safe. All calls need to come from the same thread as the player is executed on (usually the MainThread). While the collector might not crash when called from different threads, it can lead to inconsistent data.
Minification / Obfuscation
The collector uses the @Keep
annotation to prevent minification/obfuscation of request and response classes. There could be issues with certain obfuscation/minification tools though (seen with DexGuard
for example), and the following rules should be applied in these cases:
#### Bitmovin Analytics
-keep class com.bitmovin.analytics.data.** { *; }
-keep class com.bitmovin.analytics.features.** { *; }
-keep class com.bitmovin.analytics.license.** { *; }
Common Integration Pitfalls
Media3-Exoplayer
AbstractMethodError in media3 AnalyticsListener
Depending on the Release Configuration, Default Methods of media3 AnalyticsListener might be stripped away, which leads to an AbstractMethodError
with a StackTrace similar to below:
java.lang.AbstractMethodError: abstract method "void androidx.media3.exoplayer.analytics.AnalyticsListener.onPlayerStateChanged(androidx.media3.exoplayer.analytics.AnalyticsListener$EventTime, boolean, int)"
at androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector.lambda$onPlayerStateChanged$36(DefaultAnalyticsCollector.java:549)
at androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector$$ExternalSyntheticLambda17.invoke(D8$$SyntheticClass:0)
at androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(ListenerSet.java:339)
To fix the issue the following gradle setting needs to be applied in the gradle.properties
file:
android.useFullClasspathForDexingTransform = true
This issue arises due to a bug with desugaring and default Methods of Kotlin/Java.
Reference: https://issuetracker.google.com/issues/230454566
Examples
You can find fully functional code examples in our Github Repository.
Updated 6 days ago