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