• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1---
2title: APK shrinking
3---
4
5Minimizing APK size is an important aspect of developing a good Android
6application. This is particularly true when targeting developing markets, and
7also when developing an Android Instant App. For such cases it may be desirable
8to minimize the size of the ExoPlayer library that's included in the APK. This
9page outlines some simple steps that can help to achieve this.
10
11## Use modular dependencies ##
12
13The most convenient way to use ExoPlayer is to add a dependency to the full
14library:
15
16~~~
17implementation 'com.google.android.exoplayer:exoplayer:2.X.X'
18~~~
19{: .language-gradle}
20
21However this may pull in more features than your app needs. Instead, depend only
22on the library modules that you actually need. For example the following will
23add dependencies on the Core, DASH and UI library modules, as might be required
24for an app that only plays DASH content:
25
26~~~
27implementation 'com.google.android.exoplayer:exoplayer-core:2.X.X'
28implementation 'com.google.android.exoplayer:exoplayer-dash:2.X.X'
29implementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X'
30~~~
31{: .language-gradle}
32
33## Enable code and resource shrinking ##
34
35You should enable code and resource shrinking for your application's release
36builds. ExoPlayer is structured in a way that allows code shrinking to
37effectively remove unused functionality. For example, for an application that
38plays DASH content, ExoPlayer's contribution to APK size can be reduced by
39approximately 40% by enabling code shrinking.
40
41Read [Shrink, obfuscate, and optimize your app][] on the Android Developer site
42to learn how to enable code and resource shrinking.
43
44## Specify which renderers your app needs ##
45
46By default, the player's renderers will be created using
47`DefaultRenderersFactory`. `DefaultRenderersFactory` depends on all of the
48`Renderer` implementations provided in the ExoPlayer library, and as a result
49none of them will be removed by code shrinking. If you know that your app only
50needs a subset of renderers, you can specify your own `RenderersFactory`
51instead. For example, an app that only plays audio can define a factory like
52this when instantiating `ExoPlayer` instances:
53
54~~~
55RenderersFactory audioOnlyRenderersFactory =
56    (handler, videoListener, audioListener, textOutput, metadataOutput)
57        -> new Renderer[] {
58            new MediaCodecAudioRenderer(
59                context, MediaCodecSelector.DEFAULT, handler, audioListener)
60           };
61ExoPlayer player =
62    new ExoPlayer.Builder(context, audioOnlyRenderersFactory).build();
63~~~
64{: .language-java}
65
66This will allow other `Renderer` implementations to be removed by code
67shrinking. In this particular example video, text and metadata renderers are
68removed.
69
70## Specify which extractors your app needs ##
71
72By default, the player will create `Extractor`s to play progressive media using
73`DefaultExtractorsFactory`. `DefaultExtractorsFactory` depends on all of the
74`Extractor` implementations provided in the ExoPlayer library, and as a result
75none of them will be removed by code shrinking. If you know that your app only
76needs to play a small number of container formats, or doesn't play progressive
77media at all, you can specify your own `ExtractorsFactory` instead. For example,
78an app that only needs to play mp4 files can provide a factory like:
79
80~~~
81ExtractorsFactory mp4ExtractorFactory =
82    () -> new Extractor[] {new Mp4Extractor()};
83ExoPlayer player =
84    new ExoPlayer.Builder(
85           context,
86           new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
87        .build();
88~~~
89{: .language-java}
90
91This will allow other `Extractor` implementations to be removed by code
92shrinking, which can result in a significant reduction in size.
93
94If your app is not playing progressive content at all, you should pass
95`ExtractorsFactory.EMPTY` to the `DefaultMediaSourceFactory` constructor, then
96pass that `mediaSourceFactory` to the `ExoPlayer.Builder` constructor.
97
98~~~
99ExoPlayer player =
100    new ExoPlayer.Builder(
101             context,
102             new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
103         .build();
104~~~
105{: .language-java}
106
107## Custom MediaSource instantiation ##
108
109If your app is using a custom `MediaSource.Factory` and you want
110`DefaultMediaSourceFactory` to be removed by code stripping, you should pass
111your `MediaSource.Factory` directly to the `ExoPlayer.Builder` constructor.
112
113~~~
114ExoPlayer player =
115    new ExoPlayer.Builder(context, customMediaSourceFactory).build();
116~~~
117{: .language-java}
118
119If your app is using `MediaSource`s directly instead of `MediaItem`s you should
120pass `MediaSource.Factory.UNSUPPORTED` to the `ExoPlayer.Builder` constructor,
121to ensure `DefaultMediaSourceFactory` and `DefaultExtractorsFactory` can be
122stripped by code shrinking.
123
124~~~
125ExoPlayer player =
126    new ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build();
127ProgressiveMediaSource mediaSource =
128    new ProgressiveMediaSource.Factory(
129            dataSourceFactory, customExtractorsFactory)
130        .createMediaSource(MediaItem.fromUri(uri));
131~~~
132{: .language-java}
133
134[Shrink, obfuscate, and optimize your app]: https://developer.android.com/studio/build/shrink-code
135