Monitor ExoPlayer (Android)

The FastPix Data SDK with ExoPlayer helps you track key video metrics like user interactions, playback quality, and performance to enhance the viewing experience. It lets you customize data tracking, monitor streaming quality, and securely send insights for better optimization and error resolution.

Key features:

  • Capture user engagement through detailed viewer interaction data.
  • Monitor playback quality with real-time performance analysis.
  • Identify and fix video delivery bottlenecks on Android.
  • Customize tracking to match specific monitoring needs.
  • Handle errors with robust reporting and diagnostics.
  • Gain deep insights into video performance with streaming diagnostics.


Prerequisites

  1. To track and analyze video performance, initialize the FastPix Data SDK with your Workspace key. This key is essential for client-side monitoring and must be included in your Android application's code wherever you want to track video performance.
  2. An existing Android Studio project where you plan to integrate the FastPix Data SDK.
  3. Gradle configured in your project for managing dependencies.
  4. ExoPlayer pre-installed and integrated with your project for FastPix data setup.

Step 1: Install and setup

  1. Open your Android Studio project where you want to integrate the SDK.

  2. Add the FastPix Data SDK dependency:

    Navigate to your app-level build.gradle file (or build.gradle.kts if using Kotlin DSL).


    //Add the following line under the dependencies section: 
    dependencies{ 
      
    	// check with latest version 
      implementation 'io.fastpix.data:exoplayer:1.0.0 ' 
    } 

    Navigate to your settings.gradle file


    //Add the following lines inside repositories section: 
    repositories { 
      maven { 
      url = uri("https://maven.pkg.github.com/FastPix/android-data-exo-player-sdk")  
      credentials { 
    
      // Your GitHub account username (or) FastPix  
      username = "Github_User_Name" 
    
      // Your (PAT) Personal access token Get It from you Github account 
      password = "Github_PAT"   
       	      } 
      	} 
    } 

  1. Sync your project with Gradle files

    Click "Sync Now" in the notification bar to download and integrate the FastPix Data SDK.


Once the above dependency is added, you can use the FastPix Data SDK module into your Android project where you intend to use its functionalities.


PLEASE NOTE
To ensure accurate analytics, initialize and complete the ExoPlayer setup first. Once the player is fully ready, integrate and start the Android data analytics SDK in your project.


Step 2: Import

import io.fastpix.data.entity.* 
import io.fastpix.data.exo.FastPixBaseExoPlayer 
import io.fastpix.data.request.CustomOptions 

Step 3: Basic integration


Globally declare

To globally declare the ExoPlayer instance and FastPixBaseExoPlayer in your Android application. A global declaration ensures that these objects can be accessed throughout the lifecycle of your activity or application where required.


import ... 

class VideoPlayerActivity : AppCompatActivity() { 
    private lateinit var exoPlayer: ExoPlayer // Global ExoPlayer instance 
    private lateinit var fastPixBaseExoPlayer: FastPixBaseExoPlayer // Global FastPix instance 
} 

You can initialize ExoPlayer with a PlayerView or SurfaceView in your Android application to enable seamless functionality. Use the following Kotlin or Java code in your Android application to configure ExoPlayer with FastPix:


import io.fastpix.data.entity.* 
import io.fastpix.data.exo.FastPixBaseExoPlayer 
import io.fastpix.data.request.CustomOptions 

class VideoPlayerActivity : AppCompatActivity() { 

    private lateinit var exoPlayer: ExoPlayer 
    private lateinit var fastPixBaseExoPlayer: FastPixBaseExoPlayer 
  
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 

        // setContentView(R.layout.your_layout) // don't forget this if needed 
        initializePlayers() 
    } 

    private fun initializePlayers() { 

        // Initialize ExoPlayer 
        exoPlayer = ExoPlayer.Builder(this).build() 
        val mediaItem = MediaItem.fromUri("https://your.video.url/here.mp4") 
        exoPlayer.setMediaItem(mediaItem) 
        exoPlayer.prepare() 

        // Prepare Customer Data 
        val customerPlayerDataEntity = CustomerPlayerDataEntity().apply { 
            workspaceKey = Constants.envKeyFp 
        } 
        val customerVideoDataEntity = CustomerVideoDataEntity().apply { 
            videoId = "Video ID" 
            videoTitle = "Video Title" 
        } 
        val customerViewDataEntity = CustomerViewDataEntity().apply { 
            viewSessionId = UUID.randomUUID().toString() 
        } 
  
        val customDataEntity = CustomDataEntity().apply { 
            customData1 = "Data 1" 
            customData2 = "Data 2" 

            // ... 
            customData10 = "Data 10" 
        } 
  
        val customerDataEntity = CustomerDataEntity( 
            customerPlayerDataEntity, 
            customerVideoDataEntity, 
            customerViewDataEntity 

        ).apply { 
            setCustomData(customDataEntity) 

        } 
  
        // Initialize FastPixBaseExoPlayer 
        fastPixBaseExoPlayer = FastPixBaseExoPlayer( 
            this, 
            exoPlayer, 
            customerDataEntity, 
            CustomOptions() // Optional if your constructor allows default 
        ) 
  
        fastPixBaseExoPlayer.setPlayerView(playerView) // replace with actual view binding 
    } 
} 
import io.fastpix.data.entity.CustomDataEntity; 
import io.fastpix.data.entity.CustomerDataEntity; 
import io.fastpix.data.entity.CustomerPlayerDataEntity; 
import io.fastpix.data.entity.CustomerVideoDataEntity; 
import io.fastpix.data.entity.CustomerViewDataEntity; 
import io.fastpix.data.exo.FastPixBaseExoPlayer; 
import io.fastpix.data.request.CustomOptions; 

public class VideoPlayerActivity extends AppCompatActivity { 
  
    private ExoPlayer exoPlayer; 
    private FastPixBaseExoPlayer fastPixBaseExoPlayer; 
  
    // You’ll need to define this or use ViewBinding 
    private PlayerView playerView;  

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        // setContentView(R.layout.your_layout); // Make sure this matches your layout XML 
        // Example: playerView = findViewById(R.id.player_view); 
        initializePlayers(); 

    } 
  
    private void initializePlayers() { 

        // 1. Initialize ExoPlayer 
        exoPlayer = new ExoPlayer.Builder(this).build(); 
        MediaItem mediaItem = MediaItem.fromUri("https://your.video.url/here.mp4"); 
        exoPlayer.setMediaItem(mediaItem); 
        exoPlayer.prepare(); 

        // 2. Customer Data 
        CustomerPlayerDataEntity playerData = new CustomerPlayerDataEntity(); 
        playerData.setWorkspaceKey(Constants.envKeyFp); 
        CustomerVideoDataEntity videoData = new CustomerVideoDataEntity(); 
        videoData.setVideoId("Video ID"); 
        videoData.setVideoTitle("Video Title"); 
        CustomerViewDataEntity viewData = new CustomerViewDataEntity(); 
        viewData.setViewSessionId(UUID.randomUUID().toString()); 
        CustomDataEntity customData = new CustomDataEntity(); 
        customData.setCustomData1("Data 1"); 
        customData.setCustomData2("Data 2"); 

        // ... up to 
        customData.setCustomData10("Data 10"); 
        CustomerDataEntity customerData = new CustomerDataEntity( 
            playerData, 
            videoData, 
            viewData 
        ); 
        customerData.setCustomData(customData); 
  
        // 3. FastPix Setup 
        fastPixBaseExoPlayer = new FastPixBaseExoPlayer( 
            this, 
            exoPlayer, 
            customerData, 
            new CustomOptions() // optional if default constructor exists 
        ); 
  
        // 4. Attach PlayerView 
        fastPixBaseExoPlayer.setPlayerView(playerView); 
    } 
} 

Step 4: Including custom data and metadata:

workspaceKey is the only mandatory field. While all metadata fields are optional, including more information enhances the insights you can gain.

Check out the user-passable metadata documentation to see the metadata supported by FastPix. You can use custom metadata fields like custom_1 to custom_10 for your business logic, giving you the flexibility to pass any required values. Named attributes, such as video_title and video_id, can be passed directly as they are.


override fun onCreate(savedInstanceState: Bundle?) { 
	val customerPlayerDataEntity = CustomerPlayerDataEntity() 
	customerPlayerDataEntity.workspaceKey = Constants.wsKey 
	customerPlayerDataEntity.playerName = "Exoplayer" 

 
/* Data about this video Add or change properties here to customize video metadata such as title, language, etc */ 
	val customerVideoDataEntity = CustomerVideoDataEntity () 
	customerVideoDataEntity.videoId = “Id” 
	customerVideoDataEntity.videoTitle = “Title” 
	customerVideoDataEntity.videoSourceUrl = “UrlSting” 
	customerVideoDataEntity.videoLanguageCode = "Lang" 
	customerVideoDataEntity.videoProducer = "Producer" 
	customerVideoDataEntity.videoContentType = “ItemType” 
 
/* Add values for your Custom Dimensions. Up to 10 strings can be set to track your own data */ 
	val customDataEntity = CustomDataEntity () 
	customDataEntity.customData1 = "data1" 

customDataEntity.customData2 = "data2" 
	customDataEntity.customData3 = "data3" 
	     ||        ||             || 

     ||        ||             ||    

customDataEntity.customData10 = "data10" 

 
/* You need to pass the view session ID into CustomerViewDataEntity*/ 

val customerViewDataEntity = CustomerViewDataEntity ()  
	customerViewDataEntity.viewSessionId = UUID.randomUUID().toString() 
 
/* CustomerDataEntity binding with customerPlayerDataEntity, customerVideoDataEntity, customerViewDataEntity */ 
	val customerDataEntity = CustomerDataEntity ( 
	 customerPlayerDataEntity, 
	 customerVideoDataEntity, 
	 customerViewDataEntity) 

 

// CustomOptions set customized Domain or else create empty CustomOptions 
	val customOptions = CustomOptions() 
	customOptions.beaconDomain = "domain.com" 

} 

To set up video analytics, create a FastPixBaseExoPlayer object by providing the following parameters: your application's Context (usually the Activity), the ExoPlayer instance, and the CustomerDataEntity and CustomOptions objects that you have prepared.

fastPixBaseExoPlayer = FastPixBaseExoPlayer( 
    this, 
    exoPlayer, 
    customerDataEntity, 
    customOptions 
) 

If your PlayerView hasn’t been configured yet, make sure to set it up now. This step is crucial for capturing various viewer context values and accurately tracking the dimensions of the video player.

fastPixBaseExoPlayer.setPlayerView(playerView) 

Finally, when destroying the player, make sure to call the FastPixBaseExoPlayer.release() function to properly release resources.

override fun onDestroy() { 
  super.onDestroy() 
  fastPixBaseExoPlayer.release() // Cleanup FastPix tracking 
  FastPixBaseExoPlayer = null 
} 

After completing the integration, start playing a video in your player. A few minutes after stopping playback, you’ll see the results in your FastPix Video Data dashboard. Log in to the dashboard, navigate to the workspace associated with your ws_key, and look for video views.


Step 5: Advanced Customization with FastPix Data SDK


AttributeDescriptionTypeExample Usage
automaticErrorTrackingFastPix automatically tracks errors that occur during playback failures. To disable this feature, fastPixBaseExoPlayer.setAutomaticErrorTracking(false). This allows more control over which errors are considered fatal.BooleanfastPixBaseExoPlayer.setAutomaticErrorTracking(false)
debugSet to true to enable debug logs in the console for troubleshooting purposes.Booleandebug: true

automaticErrorTracking : FastPixBaseExoPlayer.setAutomaticErrorTracking = ture or false

debug: FastPixBaseExoPlayer.enableFPCoreDebug = ture or false


Step 6: Emit custom events


Configure error tracking preferences

FastPix’s integration with ExoPlayer automatically tracks fatal errors that occur within the player. However, if a fatal error occurs outside of ExoPlayer’s context and you want to log it with FastPix, you can do so by calling the fastPixBaseExoPlayer.error method.


val errorCode = 500 // Custom error code 
val errorMessage = "Description of error", // Generalized error message   
val errorContext = "Additional context for the error", // Instance-specific information  
val errorException = RequestFailureException (errorCode, errorMessage, errorContext) 
fastPixBaseExoPlayer.error(errorException) 

Note that fastPixBaseExoPlayer.error(errorException) can be used with or without automatic error tracking. If your application includes retry logic to recover from ExoPlayer errors, you may want to disable automatic error tracking by doing the following:


fastPixBaseExoPlayer.setAutomaticErrorTracking(false)// disable 
fastPixBaseExoPlayer.setAutomaticErrorTracking(true)// enable 

Changing video streams in player

Effective video view tracking is essential for monitoring multiple videos in the same player within your Android application. You should reset tracking in two key scenarios: when loading a new source (such as in video series or episodic content).

This is done by calling fastPixBaseExoPlayer.videoChange(CustomerVideoDataEntity), which will clear all previous video data and reset all metrics for the new video view. Refer to the Metadata section for the list of video details you can provide. While you can include any metadata when changing the video, you should primarily update the values that start with "video".

It's best to update the video information immediately after instructing the player to load the new source.


// Prepare Customer Data 
val customerVideoDataEntity = CustomerVideoDataEntity().apply { 
  videoId = "abc345" // Unique identifier for the new video 
  videoTitle = "My Other Great Video " // Title of the new video 
  videoSeries="Weekly Great Videos", // Series name if applicable 
} 

 fastPixBaseExoPlayer.videoChange(CustomerVideoDataEntity) 

Example to configure ExoPlayer with FastPix Data SDK.

Here are platform-specific examples to help you integrate the FastPix Data SDK with your ExoPlayer. Use the following Kotlin or Java code into your application:


import io.fastpix.data.entity.* 
import io.fastpix.data.exo.FastPixBaseExoPlayer 
import io.fastpix.data.request.CustomOptions 
 
class VideoPlayerActivity : AppCompatActivity() { 
 
    private lateinit var exoPlayer: ExoPlayer 
    private var fastPixBaseExoPlayer: FastPixBaseExoPlayer? = null 
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 

        // setContentView(R.layout.your_layout) // don't forget this if needed  
        initializePlayers() 
    } 

    private fun initializePlayers() { 

        // Initialize ExoPlayer 
        exoPlayer = ExoPlayer.Builder(this).build() 
        val mediaItem = MediaItem.fromUri("https://your.video.url/here.mp4") 
        exoPlayer.setMediaItem(mediaItem) 
        exoPlayer.prepare() 

        // Prepare Customer Data 
        val customerPlayerDataEntity = CustomerPlayerDataEntity().apply { 
            workspaceKey = Constants.envKeyFp 
        } 
        val customerVideoDataEntity = CustomerVideoDataEntity().apply { 
            videoId = "Video ID" 
            videoTitle = "Video Title" 
        } 

        val customerViewDataEntity = CustomerViewDataEntity().apply { 
            viewSessionId = UUID.randomUUID().toString() 
        } 

        val customDataEntity = CustomDataEntity().apply { 
            customData1 = "Data 1" 
            customData2 = "Data 2" 

            // ... 
            customData10 = "Data 10" 
        } 

        val customerDataEntity = CustomerDataEntity( 
            customerPlayerDataEntity, 
            customerVideoDataEntity, 
            customerViewDataEntity 
        ).apply { 
            setCustomData(customDataEntity) 
        } 
  
        // Initialize FastPixBaseExoPlayer 
        fastPixBaseExoPlayer = FastPixBaseExoPlayer( 
            this, 
            exoPlayer, 
            customerDataEntity, 
            CustomOptions() // Optional if your constructor allows default 
        ) 
        fastPixBaseExoPlayer?.setPlayerView(playerView) // replace with actual view binding 
    } 
    override fun onDestroy() { 
        super.onDestroy() 
        fastPixBaseExoPlayer?.release() // Cleanup FastPix tracking 
        fastPixBaseExoPlayer = null 
    } 
} 
import io.fastpix.data.entity.*; 
import io.fastpix.data.exo.FastPixBaseExoPlayer; 
import io.fastpix.data.request.CustomOptions; 
  
public class VideoPlayerActivity extends AppCompatActivity {  
    private ExoPlayer exoPlayer; 
    private FastPixBaseExoPlayer fastPixBaseExoPlayer; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 

        // setContentView(R.layout.your_layout); // don't forget this if needed 
        initializePlayers(); 
    } 

    private void initializePlayers() { 

        // Initialize ExoPlayer 
        exoPlayer = new ExoPlayer.Builder(this).build(); 
        MediaItem mediaItem = MediaItem.fromUri("https://your.video.url/here.mp4"); 
        exoPlayer.setMediaItem(mediaItem); 
        exoPlayer.prepare(); 
  
        // Prepare Customer Data 
        CustomerPlayerDataEntity customerPlayerDataEntity = new CustomerPlayerDataEntity(); 
        customerPlayerDataEntity.setWorkspaceKey(Constants.envKeyFp); 
        CustomerVideoDataEntity customerVideoDataEntity = new CustomerVideoDataEntity(); 
        customerVideoDataEntity.setVideoId("Video ID"); 
        customerVideoDataEntity.setVideoTitle("Video Title"); 
        CustomerViewDataEntity customerViewDataEntity = new CustomerViewDataEntity(); 
        customerViewDataEntity.setViewSessionId(UUID.randomUUID().toString()); 
        CustomDataEntity customDataEntity = new CustomDataEntity(); 
        customDataEntity.setCustomData1("Data 1"); 
        customDataEntity.setCustomData2("Data 2"); 

        // ... 
        customDataEntity.setCustomData10("Data 10"); 
        CustomerDataEntity customerDataEntity = new CustomerDataEntity( 
                customerPlayerDataEntity, 
                customerVideoDataEntity, 
                customerViewDataEntity 
        ); 

        customerDataEntity.setCustomData(customDataEntity); 
  
        // Initialize FastPixBaseExoPlayer 
        fastPixBaseExoPlayer = new FastPixBaseExoPlayer( 
                this, 
                exoPlayer, 
                customerDataEntity, 
                new CustomOptions() // Optional if your constructor allows default 
        ); 
  
        fastPixBaseExoPlayer.setPlayerView(playerView); // replace with actual view binding 
    } 

    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
        if (fastPixBaseExoPlayer != null) { 
            fastPixBaseExoPlayer.release(); // Cleanup FastPix tracking 
            fastPixBaseExoPlayer = null; 
        } 
    } 
}