Table of content

Getting started with the Android SDK


Overview

The Android SDK is available on Nexus.

Key Features

  • Developed in Kotlin 1.9.0 (compatible with version 1.8.20 and above)
  • Remote player management
  • Verified Google IMA integration
  • OMSDK support
  • TCF2 support
  • Access to Player events and state facilitated
  • Fullscreen playback management
  • Chromecast support

Supported versions & requirements

minSdk set to 21 (Lollipop)

Dependencies

The following dependencies are required:

  • For the Player:
androidx.fragment:fragment:1.5.7
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4
  • For advertising:
com.google.ads.interactivemedia.v3:interactivemedia:3.33.0
Note:

DM advertising SDK includes IMA Native. This will require additional dependencies to work. Those additional dependencies can be found in Android IMA SDK integration guide

Sample applications

To help you learn about our Android SDK and to facilitate testing, discover our sample SDK applications:

  • Android sample app: Download the sample app here directly on your device and explore the functionalities of the SDK in a user-friendly UI
  • Source code: Access the source code of the sample app here, customize as you wish and easily integrate the SDK into your projects
Note:

Sample applications contain provided Player IDs for testing purposes only, which shouldn’t be used in other apps.
Replace them with your own Player IDs (see how to create a Player configuration here).


Getting started

1 – Create an Android Player configuration

As a first step you need to create a custom player configuration for your Android application in your Dailymotion account. A unique Player Id will be generated which will be required for player initialization in-app, accurate monetization, targeting and attribution.

The custom player configuration can be created and managed either through the “Players” tab in the Dailymotion Studio or programmatically via the Platform API.

CMP implementation required to ensure monetization:

 

Publishers in GDPR countries are required to implement a TCF2 registered CMP (Consent Management Platform) in their native app to ensure monetization. A compliant CMP must be used to use IAB TCF2 for the creation and storage of the transparency & consent string. As Dailymotion fully supports the IAB TCF2 standard, our native SDKs and our Player can access this string received from the CMP in-app.

It’s important that the consent string is available before the Player is loading. For information on how to use a CMP in-app see here.

2 – Add the SDK to your project

  • Add our Nexus repository to your settings.gradle file by adding the lines below to the repositories block within the dependencyResolutionManagement block.
maven {
    name = "DailymotionMavenRelease"
    url = "https://mvn.dailymotion.com/repository/releases/"
}

The resulting settings.gradle should look like this:

dependencyResolutionManagement {
    ...
    repositories {
        ...
        maven {
            name = "DailymotionMavenRelease"
            url = "https://mvn.dailymotion.com/repository/releases/"
        }
        ...
    }
    ...
}
  • Add dependencies inside your application build.gradle file:
dependencies {
    ...
    implementation 'com.dailymotion.player.android:sdk:1.2.6'
    implementation 'androidx.fragment:fragment:1.5.7'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

    implementation 'com.dailymotion.player.android:ads:1.2.6'
    implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.33.0'
    ...
}
Note:

 

You don’t need to add androidx.fragment:fragment dependency if you already include the dependency androidx.appcompat:appcompat because androidx.appcompat:appcompat also includes androidx.fragment:fragment

3 – Create and add PlayerView to view hierarchy

Create a PlayerView using Dailymotion.createPlayer(...) method:

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    }
)

Explore the Android SDK Reference

Now that you’ve learned more about how to embed content using the Android SDK, you can dive deeper and see what’s possible to do to improve your integration and customize it to fit your needs with the following elements:

  • Advanced runtime parameters: On top of your Player configuration, you can add extra parameters that can change at runtime.
  • Methods: Our methods allow you to control the Player behavior, customize the user experience and create dynamic interactions.
  • Events: Work with events to capture user interactions with the Player and trigger custom actions.
  • State: Retrieve the data of your Player state

Add runtime Player parameters

While the main Player experience is controlled using the settings defined in your Player configuration from the Dailymotion Studio (Players tab) or the Platform API, additional runtime customization is achievable using client-side parameters. They allow you to specify additional Player behavior or pass in required values to a specific Player embed.

In the example below, we’re adding the following runtime parameters to the existing Player config defined in the {Player ID} placeholder:

  • startTime=15: video will start playing from second 15
  • mute=true: video will start muted

Find all available runtime parameters in the Android SDK Reference.

val playerParameters = PlayerParameters(
       startTime = 15,
       mute = true,
       defaultFullscreenOrientation = Orientation.Portrait // Set the default fullscreen orientation to portrait
)

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playlistId = "A_PLAYLIST_ID", // replace by desired playlist id
    playerParameters = playerParameter,
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    }
)

Use methods

Methods enable you to initialize and control Players programmatically. Find all available methods in the Android SDK Reference.

Example to initialize a Player:

You can initialize a Player on your app using the createPlayer() method and include your Player ID, Video ID and any other element you need.

val playerParameters = PlayerParameters(
    mute = false,
)

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playlistId = "A_PLAYLIST_ID", // replace by desired playlist id
    playerParameters = playerParameter,
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    playerListener = object : PlayerListener {
        ...
    }
    videoListener = object : VideoListener {
        ...
    }
    adListener = object : AdListener {
        ...
    }
)

Manage event listeners

Pass object implementing interface PlayerListener, VideoListener, AdListener to Dailymotion.create(...) method to listen to Player, Video, Ad events.

Find all available events in the Android SDK Reference.

Player events

To listen to Player events, pass an object implementing PlayerListener interface to Dailymotion.createPlayer(...).

PlayerListener interface provide an empty default implementation for all its method. This allows overriding / implementation of only wanted method instead of implementing all methods just for compilation sake (it also improve code readability).

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    playerListener = object : PlayerListener {
        ...
    }
)

For example, to listen to onPlayerEnd event, just implement the method onPlayerEnd():

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    playerListener = object : PlayerListener {
        override fun onPlayerEnd(playerView: PlayerView) {
            // player end event
        }
    }
)

Video events

To listen to Video events, pass an object implementing VideoListener interface to Dailymotion.createPlayer(...).

VideoListener interface provide an empty default implementation for all its method. This allows overriding / implementation of only wanted method instead of implementing all methods just for compilation sake (it also improve code readability).

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    videoListener = object : VideoListener {
        ...
    }
)

For example, to listen to onVideoEnd event, just implement the method onVideoEnd():

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    videoListener = object : VideoListener {
        override fun onVideoEnd(playerView: PlayerView) {
            // video end event
        }
    }
)

Ad events

To listen to Ad events, pass an object implementing AdListener to Dailymotion.createPlayer(...).

AdListener interface provide an empty default implementation for all its method. This allows overriding / implementation of only wanted method instead of implementing all methods just for compilation sake (it also improve code readability).

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    adListener = object : AdListener {
        ...
    }
)

For example, to listen to onAdStart event, just implement the method onAdStart():

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        ....
    },
    adListener = object : AdListener {
        override fun onAdStart(playerView: PlayerView, type: String, position: String) {
            // ad start event
        }
    }
)

Retrieve Player state

To retrieve the player state, pass an object implementing PlayerView.PlayerStateCallback to PlayerView#queryPlayerState(...)method.

playerView.queryPlayerState(object: PlayerView.PlayerStateCallback {
    fun onPlayerStateReceived(playerView: PlayerView, playerState: PlayerEvent.PlayerState)
        // Use playerState
    }
)

Find all available states in the Android SDK Reference.

Implement fullscreen

The Android SDK provides an out-of-the-box fullscreen implementation supporting navigation stack using either Android standard FragmentManager or Android Jetpack Navigation library.

The out-of-the-box implementation handles:

  • Orientation change: portrait, reverse portrait, landscape and reverse landscape
  • Native back button support: fullscreen can be exited when user taps on the device software / physical back button or by tapping on the exit fullscreen button from the player controls
  • Fullscreen will start in landscape mode
  • PlayerView controls button fullscreen state change from enter fullscreen icon from/to exit fullscreen icon

Sample applications showcasing implementation of fullscreen are available here: https://github.com/dailymotion/player-sdk-android-samples

The out-of-the-box implementation is not customizable:

For Partners wishing to implement their own fullscreen, please refer to the custom implementation section below.

Out-of-the-box implementation

To use the out-of-the-box implementation:

  • Make the device rotation a configuration change.
    Add the following code to the <activity> tag of the Activity hosting the PlayerView in the AndroidManifest.xml file.
android:configChanges="orientation|screenSize"

It’s more efficient to handle the orientation change as a device configuration change. This keeps the Activity instantiated and only invalidate the Activity layout.

Be sure to re-use the created PlayerView and avoid creating a new PlayerView on a state change: this will optimize the device battery life, bandwidth and memory consumption.

To handle correctly state management refer to: https://developer.android.com/topic/libraries/architecture/saving-states

  • Pass an object implementing PlayerListener.onFullscreenRequested(playerDialogFragment: DialogFragment) method.
Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    },
    playerListener = object : PlayerListener {
        override fun onFullscreenRequested(playerDialogFragment: DialogFragment) {
            // Show the playerDialogFragment on screen                
        }
    }
)

The code to display playerDialogFragment on screen will depend on the navigation stack used by the application. See the 2 available options below: Using FragmentManager or using Android JetPack Navigation.

Using FragmentManager

If the application is using FragmentManager, display playerDialogFragment like a standard android dialog fragment.

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    },
    playerListener = object : PlayerListener {
        override fun onFullscreenRequested(playerDialogFragment: DialogFragment) {
            // Show the playerDialogFragment on screen
           playerDialogFragment.show(this@MainActivity.supportFragmentManager, "dmPlayerFullscreenFragment")                
        }
    }
)

Using Android Jetpack Navigation

If the application is using Android Jetpack Navigation library, you will need to add the fullscreen dialog fragment to navigation graph before being able to navigate to it.

1. Add fullscreen dialog fragment to navigation graph
  • Add the fullscreen dialog fragment to your navigation graph file:
<dialog 
    android:id="@+id/FullscreenPlayerWebViewFragment" android:name="com.dailymotion.player.android.sdk.webview.fullscreen.FullscreenPlayerWebViewDialogFragment"
    android:label="FullscreenPlayerWebViewFragment"
    tools:layout="@layout/dm_sdk_fragment_dialog_fullscreen_player_webview" />
  • Add the navigation action to display the fullscreen dialog fragment inside the hosting fragment. Be sure insert the correct value of the action id attribute.
<action android:id="action_MainFragment_to_FullscreenPlayerWebViewFragment"
app:destination="@id/FullscreenPlayerWebViewFragment" />

The resulting navigation graph file should look like this:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/MainFragment">

    <fragment
        android:id="@+id/MainFragment"
android:name="com.dailymotion.player.android.jetpackfullscreen.MainFragment"
        android:label="@string/fragment_main_label"
        tools:layout="@layout/fragment_main">

        <!-- Action to Fullscreen dialog fragment -->
        <action android:id="@+id/action_MainFragment_to_FullscreenPlayerWebViewFragment"
            app:destination="@id/FullscreenPlayerWebViewFragment" />
    </fragment>

    <!-- Fullscreen dialog fragment -->
    <dialog
        android:id="@+id/FullscreenPlayerWebViewFragment"        android:name="com.dailymotion.player.android.sdk.webview.fullscreen.FullscreenPlayerWebViewDialogFragment"
        android:label="FullscreenPlayerWebViewFragment"
tools:layout="@layout/dm_sdk_fragment_dialog_fullscreen_player_webview" />

</navigation>
2. Display fullscreen dialog fragment

To display the fullscreen dialog fragment, use the action generated by Android Jetpack Navigation library:

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    },
    playerListener = object : PlayerListener {
        override fun onFullscreenRequested(playerDialogFragment: DialogFragment) {
            // Show the playerDialogFragment on screen
            findNavController()                         
.navigate(MainFragmentDirections.actionMainFragmentToFullscreenPlayerWebViewFragment())                
        }
    }
)

Custom implementation

To implement a custom fullscreen, pass an object implementing both PlayerListener.onFullscreenRequested(playerDialogFragment: DialogFragment) and PlayerListener.onFullscreenExit(playerView: PlayerView) methods:

Dailymotion.createPlayer(
    context = context,
    playerId = "MY_PLAYER_ID", // replace by desired player id
    videoId = "A_VIDEO_ID", // replace by desired video id
    playerSetupListener = object : Dailymotion.PlayerSetupListener {
        override fun onPlayerSetupSuccess(player: PlayerView) {
            // Add PlayerView to view hierarchy
        }

        override fun onPlayerSetupFailed(error: PlayerError) {
            // PlayerView setup failed
        }
    },
    playerListener = object : PlayerListener {
        override fun onFullscreenRequested(playerDialogFragment: DialogFragment) {
            super.onFullscreenRequested(playerDialogFragment)
        
            // Resize PlayerView to take whole screen space 

            // Notify PlayerView that we entered fullscreen: this will change PlayerView fullscreen button state.
            playerView.notifyFullscreenChanged()
        }

        override fun onFullscreenExit(playerView: PlayerView) {
            super.onFullscreenExit(playerView)

            // Resize PlayerView to take whole screen space

            // Notify PlayerView that we exited fullscreen: this will change PlayerView fullscreen button state.
            playerView.notifyFullscreenChanged()
        }
    }
)

A call to playerView.notifyFullscreenChanged()is necessary after entering or exiting fullscreen to update the PlayerView controls fullscreen button state.

Programmatic trigger

By default, fullscreen behaviour is triggered when an user taps on the fullscreen button from the Player controls. The SDK allows fullscreen behaviour to be triggered programatically by using playerView#setFullscreen(...) method.

playerView.setFullscreen(fullscreen = true) // Enter fullscreen

playerView.setFullscreen(fullscreen = false) // Exit fullscreen

playerView.setFullscreen(fullscreen = true, orientation = Orientation.Portrait) // Enter fullscreen in portrait

By default, fullscreen orientation is Landscape but it can be changed while creating PlayerView by setting the runtime parameter defaultFullscreenOrientation to another available value within the PlayerParameters object. Check the dedicated guide to see how to use runtime parameters on the Android SDK.

Implement Chromecast

The Dailymotion Cast SDK allows you to easily integrate a casting feature on your Dailymotion Player with minimum requirements.

Optional Chromecast moduleThe iOS SDK can be integrated without the Chromecast module which is optional and can be excluded based on your project requirements.:

The Android SDK can be integrated without the Chromecast module, which is optional and can be excluded based on your project requirements.

Demo:

Check our sample apps for an example on how to use, integrate and customise the cast feature with the Dailymotion Player on an Android environment

Prerequisites

1. Add Cast SDKs dependencies

Add Dailymotion Cast SDK and Google Cast SDK dependencies in your build.gradle:

dependencies {
    ...
    implementation 'com.dailymotion.player.android:cast:1.2.6'
    implementation 'androidx.mediarouter:mediarouter:1.6.0'
    implementation 'com.google.android.gms:play-services-cast-framework:21.4.0'
    ...
}

In addition to those dependencies, you may need to include additional dependencies needed by the Google Cast SDK. Please check Google Cast documentation to make sure to include them all.

2. Create an Expanded Controller

To improve the casting experience, create an expanded controller using Google Cast SDK’s widget ExpandedControlsActivity.

Refer to Google Cast SDK documentation to see this step in more details.

You can create a simple ExpandedControlsActivity as shown below:

package com.dailymotion.sample.player.sdk.cast
 
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import android.view.Menu
import com.dailymotion.sample.player.sdk.R
import com.google.android.gms.cast.framework.CastButtonFactory
 
/**
 * An example of extending [ExpandedControllerActivity] to add a cast button.
 */
class ExpandedControlsActivity : ExpandedControllerActivity() {
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.onCreateOptionsMenu(menu)
        menuInflater.inflate(R.menu.menu_cast_expanded_controller, menu)
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
        return true
    }
}

With menu_cast_expanded_controller being:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
 
    <item
        android:id="@+id/media_route_menu_item"
        android:orderInCategory="101"
        android:title="@string/cast_media_route_menu_title"
        app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
        app:showAsAction="always" />
 
</menu>

3. Modify your CastOptionsProvider

In your CastOptionsProvider class used to create the OptionsProvider, call DailymotionCast.castOptionsBuilder() to get a pre-built CastOptions.Builder that already includes a receiver application id.

An example CastOptionsProvider using our Dailymotion Cast SDK would look like this:

package com.dailymotion.sample.player.sdk.cast
 
import android.content.Context
import com.dailymotion.player.android.sdk.cast.DailymotionCast
import com.google.android.gms.cast.LaunchOptions
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.SessionProvider
import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.MediaIntentReceiver
import com.google.android.gms.cast.framework.media.NotificationOptions
 
class CastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
 
        val buttonActions = listOf(
            MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK,
            MediaIntentReceiver.ACTION_STOP_CASTING
        )
 
        // Showing "play/pause" and "stop casting" in the compat view of the notification.
        val compatButtonActionsIndices = intArrayOf(0, 1)
 
        // Use our sample ExpandedControlsActivity
        val notificationOptions = NotificationOptions.Builder()
            .setActions(buttonActions, compatButtonActionsIndices)
            .setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
 
        // Use our sample ExpandedControlsActivity
        val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
 
        val launchOptions = LaunchOptions.Builder()
            .setAndroidReceiverCompatible(true)
            .build()
 
        // Call DailymotionCast.castOptionsBuilder() to have a pre-built CastOptions.Builder
        // with an already set receiver application id
        return DailymotionCast.castOptionsBuilder()
            .setLaunchOptions(launchOptions)
            .setCastMediaOptions(mediaOptions)
            .build()
    }
 
    override fun getAdditionalSessionProviders(context: Context): MutableList<SessionProvider>? {
        return null
    }
}

4. Add Cast button

The Dailymotion Cast SDK handles communication between a casting device and the Dailymotion Player. However, in order to initiate a casting session, you need to add a Cast button in the UI. 

Refer to the Google Cast SDK documentation to see how to add a Cast button.

5. Customize the UI (Optional)

If you want to customize the appearance of the Cast button, Mini Controller and Expanded Controller, please refer to the Google Cast SDK documentation to customize the UI

Destroy/Release the Player

The Player instance can be automatically destroyed by the Android System garbage collector by setting the Player view to null or by removing all references to the Player.

However, in some cases, the Android garbage collector may take some time to run, you can manually destroy the Player using the destroy method.

After invoking PlayerView#destroy()PlayerView object will become useless since the underlying Player is destroyed. All PlayerView method calls will then result in doing nothing except printing a log in Logcat to warn about illegal usage of a destroyed Player:
“Tried to perform command with a destroyed player. Ignoring command.”

To invoke PlayerView#destroy() method, simply call it:

playerView.destroy()