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