1*30877f79SAndroid Build Coastguard Worker--- 2*30877f79SAndroid Build Coastguard Workertitle: Demo application 3*30877f79SAndroid Build Coastguard Worker--- 4*30877f79SAndroid Build Coastguard Worker 5*30877f79SAndroid Build Coastguard WorkerExoPlayer's main demo app serves two primary purposes: 6*30877f79SAndroid Build Coastguard Worker 7*30877f79SAndroid Build Coastguard Worker1. To provide a relatively simple yet fully featured example of ExoPlayer usage. 8*30877f79SAndroid Build Coastguard Worker The demo app can be used as a convenient starting point from which to develop 9*30877f79SAndroid Build Coastguard Worker your own application. 10*30877f79SAndroid Build Coastguard Worker1. To make it easy to try ExoPlayer. The demo app can be used to test playback 11*30877f79SAndroid Build Coastguard Worker of your own content in addition to the included samples. 12*30877f79SAndroid Build Coastguard Worker 13*30877f79SAndroid Build Coastguard WorkerThis page describes how to get, compile and run the demo app. It also describes 14*30877f79SAndroid Build Coastguard Workerhow to use it to play your own media. 15*30877f79SAndroid Build Coastguard Worker 16*30877f79SAndroid Build Coastguard Worker## Getting the code ## 17*30877f79SAndroid Build Coastguard Worker 18*30877f79SAndroid Build Coastguard WorkerThe source code for the main demo app can be found in the `demos/main` folder of 19*30877f79SAndroid Build Coastguard Workerour [GitHub project][]. If you haven't already done so, clone the project into a 20*30877f79SAndroid Build Coastguard Workerlocal directory: 21*30877f79SAndroid Build Coastguard Worker 22*30877f79SAndroid Build Coastguard Worker~~~ 23*30877f79SAndroid Build Coastguard Workergit clone https://github.com/google/ExoPlayer.git 24*30877f79SAndroid Build Coastguard Worker~~~ 25*30877f79SAndroid Build Coastguard Worker{: .language-shell} 26*30877f79SAndroid Build Coastguard Worker 27*30877f79SAndroid Build Coastguard WorkerNext, open the project in Android Studio. You should see the following in the 28*30877f79SAndroid Build Coastguard WorkerAndroid Project view (the relevant folders of the demo app have been expanded): 29*30877f79SAndroid Build Coastguard Worker 30*30877f79SAndroid Build Coastguard Worker{% include figure.html url="/images/demo-app-project.png" index="1" caption="The project in Android Studio" %} 31*30877f79SAndroid Build Coastguard Worker 32*30877f79SAndroid Build Coastguard Worker## Compiling and running ## 33*30877f79SAndroid Build Coastguard Worker 34*30877f79SAndroid Build Coastguard WorkerTo compile and run the demo app, select and run the `demo` configuration in 35*30877f79SAndroid Build Coastguard WorkerAndroid Studio. The demo app will install and run on a connected Android device. 36*30877f79SAndroid Build Coastguard WorkerWe recommend using a physical device if possible. If you wish to use an emulator 37*30877f79SAndroid Build Coastguard Workerinstead, please read the emulators section of [Supported devices][] and ensure 38*30877f79SAndroid Build Coastguard Workerthat your Virtual Device uses a system image with an API level of at least 23. 39*30877f79SAndroid Build Coastguard Worker 40*30877f79SAndroid Build Coastguard Worker{% include figure.html url="/images/demo-app-screenshots.png" index="2" caption="SampleChooserActivity and PlayerActivity" %} 41*30877f79SAndroid Build Coastguard Worker 42*30877f79SAndroid Build Coastguard WorkerThe demo app presents of a list of samples (`SampleChooserActivity`). Selecting 43*30877f79SAndroid Build Coastguard Workera sample will open a second activity (`PlayerActivity`) for playback. The demo 44*30877f79SAndroid Build Coastguard Workerfeatures playback controls and track selection functionality. It also uses 45*30877f79SAndroid Build Coastguard WorkerExoPlayer's `EventLogger` utility class to output useful debug information to 46*30877f79SAndroid Build Coastguard Workerthe system log. This logging can be viewed (along with error level logging for 47*30877f79SAndroid Build Coastguard Workerother tags) with the command: 48*30877f79SAndroid Build Coastguard Worker 49*30877f79SAndroid Build Coastguard Worker~~~ 50*30877f79SAndroid Build Coastguard Workeradb logcat EventLogger:V *:E 51*30877f79SAndroid Build Coastguard Worker~~~ 52*30877f79SAndroid Build Coastguard Worker{: .language-shell} 53*30877f79SAndroid Build Coastguard Worker 54*30877f79SAndroid Build Coastguard Worker### Enabling extension decoders ### 55*30877f79SAndroid Build Coastguard Worker 56*30877f79SAndroid Build Coastguard WorkerExoPlayer has a number of extensions that allow use of bundled software 57*30877f79SAndroid Build Coastguard Workerdecoders, including AV1, VP9, Opus, FLAC and FFmpeg (audio only). The demo app 58*30877f79SAndroid Build Coastguard Workercan be built to include and use these extensions as follows: 59*30877f79SAndroid Build Coastguard Worker 60*30877f79SAndroid Build Coastguard Worker1. Build each of the extensions that you want to include. Note that this is a 61*30877f79SAndroid Build Coastguard Worker manual process. Refer to the `README.md` file in each extension for 62*30877f79SAndroid Build Coastguard Worker instructions. 63*30877f79SAndroid Build Coastguard Worker1. In Android Studio's Build Variants view, set the build variant for the demo 64*30877f79SAndroid Build Coastguard Worker module to `withDecoderExtensionsDebug` or `withDecoderExtensionsRelease` as 65*30877f79SAndroid Build Coastguard Worker shown below. 66*30877f79SAndroid Build Coastguard Worker1. Compile, install and run the `demo` configuration as normal. 67*30877f79SAndroid Build Coastguard Worker 68*30877f79SAndroid Build Coastguard Worker{% include figure.html url="/images/demo-app-build-variants.png" index="3" caption="Selecting the demo withDecoderExtensionsDebug build variant" %} 69*30877f79SAndroid Build Coastguard Worker 70*30877f79SAndroid Build Coastguard WorkerBy default an extension decoder will be used only if a suitable platform decoder 71*30877f79SAndroid Build Coastguard Workerdoes not exist. It is possible to specify that extension decoders should be 72*30877f79SAndroid Build Coastguard Workerpreferred, as described in the sections below. 73*30877f79SAndroid Build Coastguard Worker 74*30877f79SAndroid Build Coastguard Worker## Playing your own content ## 75*30877f79SAndroid Build Coastguard Worker 76*30877f79SAndroid Build Coastguard WorkerThere are multiple ways to play your own content in the demo app. 77*30877f79SAndroid Build Coastguard Worker 78*30877f79SAndroid Build Coastguard Worker### 1. Editing assets/media.exolist.json ### 79*30877f79SAndroid Build Coastguard Worker 80*30877f79SAndroid Build Coastguard WorkerThe samples listed in the demo app are loaded from `assets/media.exolist.json`. 81*30877f79SAndroid Build Coastguard WorkerBy editing this JSON file it's possible to add and remove samples from the demo 82*30877f79SAndroid Build Coastguard Workerapp. The schema is as follows, where [O] indicates an optional attribute. 83*30877f79SAndroid Build Coastguard Worker 84*30877f79SAndroid Build Coastguard Worker~~~ 85*30877f79SAndroid Build Coastguard Worker[ 86*30877f79SAndroid Build Coastguard Worker { 87*30877f79SAndroid Build Coastguard Worker "name": "Name of heading", 88*30877f79SAndroid Build Coastguard Worker "samples": [ 89*30877f79SAndroid Build Coastguard Worker { 90*30877f79SAndroid Build Coastguard Worker "name": "Name of sample", 91*30877f79SAndroid Build Coastguard Worker "uri": "The URI of the sample", 92*30877f79SAndroid Build Coastguard Worker "extension": "[O] Sample type hint. Values: mpd, ism, m3u8", 93*30877f79SAndroid Build Coastguard Worker "clip_start_position_ms": "[O] A start point to which the sample should be clipped, in milliseconds" 94*30877f79SAndroid Build Coastguard Worker "clip_end_position_ms": "[O] An end point from which the sample should be clipped, in milliseconds" 95*30877f79SAndroid Build Coastguard Worker "drm_scheme": "[O] Drm scheme if protected. Values: widevine, playready, clearkey", 96*30877f79SAndroid Build Coastguard Worker "drm_license_uri": "[O] URI of the license server if protected", 97*30877f79SAndroid Build Coastguard Worker "drm_force_default_license_uri": "[O] Whether to force use of "drm_license_uri" for key requests that include their own license URI", 98*30877f79SAndroid Build Coastguard Worker "drm_key_request_properties": "[O] Key request headers if protected", 99*30877f79SAndroid Build Coastguard Worker "drm_session_for_clear_content": "[O] Whether to attach a DRM session to clear video and audio tracks" 100*30877f79SAndroid Build Coastguard Worker "drm_multi_session": "[O] Enables key rotation if protected", 101*30877f79SAndroid Build Coastguard Worker "subtitle_uri": "[O] The URI of a subtitle sidecar file", 102*30877f79SAndroid Build Coastguard Worker "subtitle_mime_type": "[O] The MIME type of subtitle_uri (required if subtitle_uri is set)", 103*30877f79SAndroid Build Coastguard Worker "subtitle_language": "[O] The BCP47 language code of the subtitle file (ignored if subtitle_uri is not set)", 104*30877f79SAndroid Build Coastguard Worker "ad_tag_uri": "[O] The URI of an ad tag to load via the IMA extension" 105*30877f79SAndroid Build Coastguard Worker }, 106*30877f79SAndroid Build Coastguard Worker ...etc 107*30877f79SAndroid Build Coastguard Worker ] 108*30877f79SAndroid Build Coastguard Worker }, 109*30877f79SAndroid Build Coastguard Worker ...etc 110*30877f79SAndroid Build Coastguard Worker] 111*30877f79SAndroid Build Coastguard Worker~~~ 112*30877f79SAndroid Build Coastguard Worker{: .language-json} 113*30877f79SAndroid Build Coastguard Worker 114*30877f79SAndroid Build Coastguard WorkerPlaylists of samples can be specified using the schema: 115*30877f79SAndroid Build Coastguard Worker 116*30877f79SAndroid Build Coastguard Worker~~~ 117*30877f79SAndroid Build Coastguard Worker[ 118*30877f79SAndroid Build Coastguard Worker { 119*30877f79SAndroid Build Coastguard Worker "name": "Name of heading", 120*30877f79SAndroid Build Coastguard Worker "samples": [ 121*30877f79SAndroid Build Coastguard Worker { 122*30877f79SAndroid Build Coastguard Worker "name": "Name of playlist sample", 123*30877f79SAndroid Build Coastguard Worker "playlist": [ 124*30877f79SAndroid Build Coastguard Worker { 125*30877f79SAndroid Build Coastguard Worker "uri": "The URI of the first sample in the playlist", 126*30877f79SAndroid Build Coastguard Worker "extension": "[O] Sample type hint. Values: mpd, ism, m3u8" 127*30877f79SAndroid Build Coastguard Worker "clip_start_position_ms": "[O] A start point to which the sample should be clipped, in milliseconds" 128*30877f79SAndroid Build Coastguard Worker "clip_end_position_ms": "[O] An end point from which the sample should be clipped, in milliseconds" 129*30877f79SAndroid Build Coastguard Worker "drm_scheme": "[O] Drm scheme if protected. Values: widevine, playready, clearkey", 130*30877f79SAndroid Build Coastguard Worker "drm_license_uri": "[O] URI of the license server if protected", 131*30877f79SAndroid Build Coastguard Worker "drm_force_default_license_uri": "[O] Whether to force use of "drm_license_uri" for key requests that include their own license URI", 132*30877f79SAndroid Build Coastguard Worker "drm_key_request_properties": "[O] Key request headers if protected", 133*30877f79SAndroid Build Coastguard Worker "drm_session_for_clear_content": "[O] Whether to attach a DRM session to clear video and audio tracks", 134*30877f79SAndroid Build Coastguard Worker "drm_multi_session": "[O] Enables key rotation if protected", 135*30877f79SAndroid Build Coastguard Worker "subtitle_uri": "[O] The URI of a subtitle sidecar file", 136*30877f79SAndroid Build Coastguard Worker "subtitle_mime_type": "[O] The MIME type of subtitle_uri (required if subtitle_uri is set)", 137*30877f79SAndroid Build Coastguard Worker "subtitle_language": "[O] The BCP47 language code of the subtitle file (ignored if subtitle_uri is not set)" 138*30877f79SAndroid Build Coastguard Worker }, 139*30877f79SAndroid Build Coastguard Worker { 140*30877f79SAndroid Build Coastguard Worker "uri": "The URI of the second sample in the playlist", 141*30877f79SAndroid Build Coastguard Worker ...etc 142*30877f79SAndroid Build Coastguard Worker }, 143*30877f79SAndroid Build Coastguard Worker ...etc 144*30877f79SAndroid Build Coastguard Worker ] 145*30877f79SAndroid Build Coastguard Worker }, 146*30877f79SAndroid Build Coastguard Worker ...etc 147*30877f79SAndroid Build Coastguard Worker ] 148*30877f79SAndroid Build Coastguard Worker }, 149*30877f79SAndroid Build Coastguard Worker ...etc 150*30877f79SAndroid Build Coastguard Worker] 151*30877f79SAndroid Build Coastguard Worker~~~ 152*30877f79SAndroid Build Coastguard Worker{: .language-json} 153*30877f79SAndroid Build Coastguard Worker 154*30877f79SAndroid Build Coastguard WorkerIf required, key request headers are specified as an object containing a string 155*30877f79SAndroid Build Coastguard Workerattribute for each header: 156*30877f79SAndroid Build Coastguard Worker 157*30877f79SAndroid Build Coastguard Worker~~~ 158*30877f79SAndroid Build Coastguard Worker"drm_key_request_properties": { 159*30877f79SAndroid Build Coastguard Worker "name1": "value1", 160*30877f79SAndroid Build Coastguard Worker "name2": "value2", 161*30877f79SAndroid Build Coastguard Worker ...etc 162*30877f79SAndroid Build Coastguard Worker} 163*30877f79SAndroid Build Coastguard Worker~~~ 164*30877f79SAndroid Build Coastguard Worker{: .language-json} 165*30877f79SAndroid Build Coastguard Worker 166*30877f79SAndroid Build Coastguard WorkerIn the sample chooser activity, the overflow menu contains options for 167*30877f79SAndroid Build Coastguard Workerspecifying whether to prefer extension decoders. 168*30877f79SAndroid Build Coastguard Worker 169*30877f79SAndroid Build Coastguard Worker### 2. Loading an external exolist.json file ### 170*30877f79SAndroid Build Coastguard Worker 171*30877f79SAndroid Build Coastguard WorkerThe demo app can load external JSON files using the schema above and named 172*30877f79SAndroid Build Coastguard Workeraccording to the `*.exolist.json` convention. For example if you host such a 173*30877f79SAndroid Build Coastguard Workerfile at `https://yourdomain.com/samples.exolist.json`, you can open it in the 174*30877f79SAndroid Build Coastguard Workerdemo app using: 175*30877f79SAndroid Build Coastguard Worker 176*30877f79SAndroid Build Coastguard Worker~~~ 177*30877f79SAndroid Build Coastguard Workeradb shell am start -a android.intent.action.VIEW \ 178*30877f79SAndroid Build Coastguard Worker -d https://yourdomain.com/samples.exolist.json 179*30877f79SAndroid Build Coastguard Worker~~~ 180*30877f79SAndroid Build Coastguard Worker{: .language-shell} 181*30877f79SAndroid Build Coastguard Worker 182*30877f79SAndroid Build Coastguard WorkerClicking a `*.exolist.json` link (e.g., in the browser or an email client) on a 183*30877f79SAndroid Build Coastguard Workerdevice with the demo app installed will also open it in the demo app. Hence 184*30877f79SAndroid Build Coastguard Workerhosting a `*.exolist.json` JSON file provides a simple way of distributing 185*30877f79SAndroid Build Coastguard Workercontent for others to try in the demo app. 186*30877f79SAndroid Build Coastguard Worker 187*30877f79SAndroid Build Coastguard Worker### 3. Firing an intent ### 188*30877f79SAndroid Build Coastguard Worker 189*30877f79SAndroid Build Coastguard WorkerIntents can be used to bypass the list of samples and launch directly into 190*30877f79SAndroid Build Coastguard Workerplayback. To play a single sample set the intent's action to 191*30877f79SAndroid Build Coastguard Worker`com.google.android.exoplayer.demo.action.VIEW` and its data URI to that of the 192*30877f79SAndroid Build Coastguard Workersample to play. Such an intent can be fired from the terminal using: 193*30877f79SAndroid Build Coastguard Worker 194*30877f79SAndroid Build Coastguard Worker~~~ 195*30877f79SAndroid Build Coastguard Workeradb shell am start -a com.google.android.exoplayer.demo.action.VIEW \ 196*30877f79SAndroid Build Coastguard Worker -d https://yourdomain.com/sample.mp4 197*30877f79SAndroid Build Coastguard Worker~~~ 198*30877f79SAndroid Build Coastguard Worker{: .language-shell} 199*30877f79SAndroid Build Coastguard Worker 200*30877f79SAndroid Build Coastguard WorkerSupported optional extras for a single sample intent are: 201*30877f79SAndroid Build Coastguard Worker 202*30877f79SAndroid Build Coastguard Worker* Sample configuration extras: 203*30877f79SAndroid Build Coastguard Worker * `mime_type` [String] Sample MIME type hint. For example 204*30877f79SAndroid Build Coastguard Worker `application/dash+xml` for DASH content. 205*30877f79SAndroid Build Coastguard Worker * `clip_start_position_ms` [Long] A start point to which the sample should be 206*30877f79SAndroid Build Coastguard Worker clipped, in milliseconds. 207*30877f79SAndroid Build Coastguard Worker * `clip_end_position_ms` [Long] An end point from which the sample should be 208*30877f79SAndroid Build Coastguard Worker clipped, in milliseconds. 209*30877f79SAndroid Build Coastguard Worker * `drm_scheme` [String] DRM scheme if protected. Valid values are `widevine`, 210*30877f79SAndroid Build Coastguard Worker `playready` and `clearkey`. DRM scheme UUIDs are also accepted. 211*30877f79SAndroid Build Coastguard Worker * `drm_license_uri` [String] URI of the license server if protected. 212*30877f79SAndroid Build Coastguard Worker * `drm_force_default_license_uri` [Boolean] Whether to force use of 213*30877f79SAndroid Build Coastguard Worker `drm_license_uri` for key requests that include their own license URI. 214*30877f79SAndroid Build Coastguard Worker * `drm_key_request_properties` [String array] Key request headers packed as 215*30877f79SAndroid Build Coastguard Worker name1, value1, name2, value2 etc. if protected. 216*30877f79SAndroid Build Coastguard Worker * `drm_session_for_clear_content` [Boolean] Whether to attach a DRM session 217*30877f79SAndroid Build Coastguard Worker to clear video and audio tracks. 218*30877f79SAndroid Build Coastguard Worker * `drm_multi_session` [Boolean] Enables key rotation if protected. 219*30877f79SAndroid Build Coastguard Worker * `subtitle_uri` [String] The URI of a subtitle sidecar file. 220*30877f79SAndroid Build Coastguard Worker * `subtitle_mime_type` [String] The MIME type of subtitle_uri (required if 221*30877f79SAndroid Build Coastguard Worker subtitle_uri is set). 222*30877f79SAndroid Build Coastguard Worker * `subtitle_language` [String] The BCP47 language code of the subtitle file 223*30877f79SAndroid Build Coastguard Worker (ignored if subtitle_uri is not set). 224*30877f79SAndroid Build Coastguard Worker * `ad_tag_uri` [String] The URI of an ad tag to load using the 225*30877f79SAndroid Build Coastguard Worker [IMA extension][]. 226*30877f79SAndroid Build Coastguard Worker * `prefer_extension_decoders` [Boolean] Whether extension decoders are 227*30877f79SAndroid Build Coastguard Worker preferred to platform ones. 228*30877f79SAndroid Build Coastguard Worker 229*30877f79SAndroid Build Coastguard WorkerWhen using `adb shell am start` to fire an intent, an optional string extra can 230*30877f79SAndroid Build Coastguard Workerbe set with `--es` (e.g., `--es extension mpd`). An optional boolean extra can 231*30877f79SAndroid Build Coastguard Workerbe set with `--ez` (e.g., `--ez prefer_extension_decoders TRUE`). An optional 232*30877f79SAndroid Build Coastguard Workerlong extra can be set with `--el` (e.g., `--el clip_start_position_ms 5000`). An 233*30877f79SAndroid Build Coastguard Workeroptional string array extra can be set with `--esa` (e.g., 234*30877f79SAndroid Build Coastguard Worker`--esa drm_key_request_properties name1,value1`). 235*30877f79SAndroid Build Coastguard Worker 236*30877f79SAndroid Build Coastguard WorkerTo play a playlist of samples, set the intent's action to 237*30877f79SAndroid Build Coastguard Worker`com.google.android.exoplayer.demo.action.VIEW_LIST`. The sample configuration 238*30877f79SAndroid Build Coastguard Workerextras remain the same as for `com.google.android.exoplayer.demo.action.VIEW`, 239*30877f79SAndroid Build Coastguard Workerexcept for two differences: 240*30877f79SAndroid Build Coastguard Worker 241*30877f79SAndroid Build Coastguard Worker* The extras' keys should have an underscore and the 0-based index of the sample 242*30877f79SAndroid Build Coastguard Worker as suffix. For example, `extension_0` would hint the sample type for the first 243*30877f79SAndroid Build Coastguard Worker sample. `drm_scheme_1` would set the DRM scheme for the second sample. 244*30877f79SAndroid Build Coastguard Worker* The uri of the sample is passed as an extra with key `uri_<sample-index>`. 245*30877f79SAndroid Build Coastguard Worker 246*30877f79SAndroid Build Coastguard WorkerOther extras, which are not sample dependant, do not change. For example, you 247*30877f79SAndroid Build Coastguard Workercan run the following command in the terminal to play a playlist with two items, 248*30877f79SAndroid Build Coastguard Workeroverriding the extension of the second item: 249*30877f79SAndroid Build Coastguard Worker~~~ 250*30877f79SAndroid Build Coastguard Workeradb shell am start -a com.google.android.exoplayer.demo.action.VIEW_LIST \ 251*30877f79SAndroid Build Coastguard Worker --es uri_0 https://a.com/sample1.mp4 \ 252*30877f79SAndroid Build Coastguard Worker --es uri_1 https://b.com/sample2.fake_mpd \ 253*30877f79SAndroid Build Coastguard Worker --es extension_1 mpd 254*30877f79SAndroid Build Coastguard Worker~~~ 255*30877f79SAndroid Build Coastguard Worker{: .language-shell} 256*30877f79SAndroid Build Coastguard Worker 257*30877f79SAndroid Build Coastguard Worker[IMA extension]: {{ site.release_v2 }}/extensions/ima 258*30877f79SAndroid Build Coastguard Worker[GitHub project]: https://github.com/google/ExoPlayer 259*30877f79SAndroid Build Coastguard Worker[Supported devices]: {{ site.baseurl }}/supported-devices.html 260