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