APK 縮減
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
開發優質 Android 應用程式時,縮減 APK 大小是相當重要的一環。如果目標市場是開發中地區,或是要開發 Android 免安裝應用程式,就更是如此。在這些情況下,您可能需要盡量縮減 APK 中包含的 ExoPlayer 程式庫大小。本頁面列出幾個簡單步驟,協助您達成這個目標。
只使用必要的依附元件
只依附您實際需要的程式庫模組。舉例來說,如果應用程式只會播放 DASH 內容,可能需要依附 ExoPlayer、DASH 和 UI 程式庫模組,此時可新增下列依附元件:
Kotlin
implementation("androidx.media3:media3-exoplayer:1.8.0")
implementation("androidx.media3:media3-exoplayer-dash:1.8.0")
implementation("androidx.media3:media3-ui:1.8.0")
Groovy
implementation "androidx.media3:media3-exoplayer:1.8.0"
implementation "androidx.media3:media3-exoplayer-dash:1.8.0"
implementation "androidx.media3:media3-ui:1.8.0"
啟用程式碼和資源縮減功能
您應為應用程式的發布版本啟用程式碼和資源縮減功能。ExoPlayer 的結構可讓程式碼縮減功能有效移除未使用的功能。舉例來說,如果應用程式播放 DASH 內容,啟用程式碼縮減功能後,ExoPlayer 對 APK 大小的影響可減少約 40%。
請參閱「縮減、模糊處理及最佳化應用程式」,瞭解如何啟用程式碼和資源縮減功能。
指定應用程式需要的轉譯器
根據預設,系統會使用 DefaultRenderersFactory
建立播放器的轉譯器。DefaultRenderersFactory
依附 ExoPlayer 程式庫中提供的所有 Renderer
實作項目,因此程式碼縮減功能不會移除任何項目。如果您知道應用程式只需要部分轉譯器,可以改為指定自己的 RenderersFactory
。舉例來說,如果應用程式只會播放音訊,在例項化 ExoPlayer
例項時,可以定義如下的工廠:
Kotlin
val audioOnlyRenderersFactory =
RenderersFactory {
handler: Handler,
videoListener: VideoRendererEventListener,
audioListener: AudioRendererEventListener,
textOutput: TextOutput,
metadataOutput: MetadataOutput,
->
arrayOf<Renderer>(
MediaCodecAudioRenderer(context, MediaCodecSelector.DEFAULT, handler, audioListener)
)
}
val player = ExoPlayer.Builder(context, audioOnlyRenderersFactory).build()
Java
RenderersFactory audioOnlyRenderersFactory =
(handler, videoListener, audioListener, textOutput, metadataOutput) ->
new Renderer[] {
new MediaCodecAudioRenderer(
context, MediaCodecSelector.DEFAULT, handler, audioListener)
};
ExoPlayer player = new ExoPlayer.Builder(context, audioOnlyRenderersFactory).build();
這樣一來,程式碼縮減功能就能移除其他 Renderer
實作項目。在這個特定範例影片中,系統會移除文字和中繼資料的轉譯器 (也就是說,播放器不會處理或發出任何字幕或串流中繼資料 (例如 ICY))。
根據預設,播放器會建立 Extractor
執行個體,使用 DefaultExtractorsFactory
播放漸進式媒體。DefaultExtractorsFactory
依附 ExoPlayer 程式庫中提供的所有 Extractor
實作項目,因此程式碼縮減功能不會移除任何項目。如果您知道應用程式只需要播放少數容器格式,或完全不播放漸進式媒體,可以改為指定自己的 ExtractorsFactory
。舉例來說,如果應用程式只需要播放 mp4 檔案,可以提供如下的工廠:
Kotlin
val mp4ExtractorFactory = ExtractorsFactory {
arrayOf<Extractor>(Mp4Extractor(DefaultSubtitleParserFactory()))
}
val player =
ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, mp4ExtractorFactory)).build()
Java
ExtractorsFactory mp4ExtractorFactory =
() -> new Extractor[] {new Mp4Extractor(new DefaultSubtitleParserFactory())};
ExoPlayer player =
new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
.build();
這樣一來,程式碼縮減功能就能移除其他 Extractor
實作項目,大幅縮減大小。
如果應用程式完全沒有播放漸進式內容,您應將 ExtractorsFactory.EMPTY
傳遞至 DefaultMediaSourceFactory
建構函式,然後將該 mediaSourceFactory
傳遞至 ExoPlayer.Builder
建構函式。
Kotlin
val player =
ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()
Java
ExoPlayer player =
new ExoPlayer.Builder(
context, new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))
.build();
如果應用程式使用自訂 MediaSource.Factory
,且您想透過程式碼剝除作業移除 DefaultMediaSourceFactory
,請直接將 MediaSource.Factory
傳遞至 ExoPlayer.Builder
建構函式。
Kotlin
val player = ExoPlayer.Builder(context, customMediaSourceFactory).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();
如果應用程式直接使用 MediaSource
,而非 MediaItem
,請將 MediaSource.Factory.UNSUPPORTED
傳遞至 ExoPlayer.Builder
建構函式,確保程式碼縮減功能可以剝除 DefaultMediaSourceFactory
和 DefaultExtractorsFactory
。
Kotlin
val player = ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build()
val mediaSource =
ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
.createMediaSource(MediaItem.fromUri(uri))
Java
ExoPlayer player = new ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build();
ProgressiveMediaSource mediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)
.createMediaSource(MediaItem.fromUri(uri));
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-08-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-08-27 (世界標準時間)。"],[],[],null,["# APK shrinking\n\nMinimizing APK size is an important aspect of developing a good Android\napp. This is particularly true when targeting developing markets, and\nalso when developing an Android Instant App. For such cases, it may be desirable\nto minimize the size of the ExoPlayer library that's included in the APK. This\npage outlines some simple steps that can help to achieve this.\n\nUse only required dependencies\n------------------------------\n\nDepend only on the library modules that you actually need. For example, the\nfollowing will add dependencies on the ExoPlayer, DASH, and UI library modules,\nas might be required for an app that only plays DASH content: \n\n### Kotlin\n\n```kotlin\nimplementation(\"androidx.media3:media3-exoplayer:1.8.0\")\nimplementation(\"androidx.media3:media3-exoplayer-dash:1.8.0\")\nimplementation(\"androidx.media3:media3-ui:1.8.0\")\n```\n\n### Groovy\n\n```groovy\nimplementation \"androidx.media3:media3-exoplayer:1.8.0\"\nimplementation \"androidx.media3:media3-exoplayer-dash:1.8.0\"\nimplementation \"androidx.media3:media3-ui:1.8.0\"\n```\n\nEnable code and resource shrinking\n----------------------------------\n\nYou should enable code and resource shrinking for your app's release\nbuilds. ExoPlayer is structured in a way that allows code shrinking to\neffectively remove unused functionality. For example, for an app that\nplays DASH content, ExoPlayer's contribution to APK size can be reduced by\napproximately 40% by enabling code shrinking.\n\nRead [Shrink, obfuscate, and optimize your app](/studio/build/shrink-code) to learn how to enable\ncode and resource shrinking.\n\nSpecify which renderers your app needs\n--------------------------------------\n\nBy default, the player's renderers will be created using\n`DefaultRenderersFactory`. `DefaultRenderersFactory` depends on all of the\n`Renderer` implementations provided in the ExoPlayer library, and as a result\nnone of them will be removed by code shrinking. If you know that your app only\nneeds a subset of renderers, you can specify your own `RenderersFactory`\ninstead. For example, an app that only plays audio can define a factory like\nthis when instantiating `ExoPlayer` instances: \n\n### Kotlin\n\n```kotlin\nval audioOnlyRenderersFactory =\n RenderersFactory {\n handler: Handler,\n videoListener: VideoRendererEventListener,\n audioListener: AudioRendererEventListener,\n textOutput: TextOutput,\n metadataOutput: MetadataOutput,\n -\u003e\n arrayOf\u003cRenderer\u003e(\n MediaCodecAudioRenderer(context, MediaCodecSelector.DEFAULT, handler, audioListener)\n )\n}\nval player = ExoPlayer.Builder(context, audioOnlyRenderersFactory).build()\n```\n\n### Java\n\n```java\nRenderersFactory audioOnlyRenderersFactory =\n (handler, videoListener, audioListener, textOutput, metadataOutput) -\u003e\n new Renderer[] {\n new MediaCodecAudioRenderer(\n context, MediaCodecSelector.DEFAULT, handler, audioListener)\n };\nExoPlayer player = new ExoPlayer.Builder(context, audioOnlyRenderersFactory).build();\n```\n\n\u003cbr /\u003e\n\nThis will allow other `Renderer` implementations to be removed by code\nshrinking. In this particular example video, text and metadata renderers are\nremoved (which means any subtitles or in-stream metadata (e.g.\n[ICY](https://cast.readme.io/docs/icy)) won't be processed or emitted by the\nplayer).\n\nSpecify which extractors your app needs\n---------------------------------------\n\nBy default, the player creates `Extractor` instances to play progressive media using\n`DefaultExtractorsFactory`. `DefaultExtractorsFactory` depends on all of the\n`Extractor` implementations provided in the ExoPlayer library, and as a result\nnone of them will be removed by code shrinking. If you know that your app only\nneeds to play a small number of container formats, or doesn't play progressive\nmedia at all, you can specify your own `ExtractorsFactory` instead. For example,\nan app that only needs to play mp4 files can provide a factory like: \n\n### Kotlin\n\n```kotlin\nval mp4ExtractorFactory = ExtractorsFactory {\n arrayOf\u003cExtractor\u003e(Mp4Extractor(DefaultSubtitleParserFactory()))\n}\nval player =\n ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, mp4ExtractorFactory)).build()\n```\n\n### Java\n\n```java\nExtractorsFactory mp4ExtractorFactory =\n () -\u003e new Extractor[] {new Mp4Extractor(new DefaultSubtitleParserFactory())};\nExoPlayer player =\n new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, mp4ExtractorFactory))\n .build();\n```\n\n\u003cbr /\u003e\n\nThis will allow other `Extractor` implementations to be removed by code\nshrinking, which can result in a significant reduction in size.\n\nIf your app is not playing progressive content at all, you should pass\n`ExtractorsFactory.EMPTY` to the `DefaultMediaSourceFactory` constructor, then\npass that `mediaSourceFactory` to the `ExoPlayer.Builder` constructor. \n\n### Kotlin\n\n```kotlin\nval player =\n ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()\n```\n\n### Java\n\n```java\nExoPlayer player =\n new ExoPlayer.Builder(\n context, new DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY))\n .build();\n```\n\n\u003cbr /\u003e\n\nCustom MediaSource instantiation\n--------------------------------\n\nIf your app is using a custom `MediaSource.Factory` and you want\n`DefaultMediaSourceFactory` to be removed by code stripping, you should pass\nyour `MediaSource.Factory` directly to the `ExoPlayer.Builder` constructor. \n\n### Kotlin\n\n```kotlin\nval player = ExoPlayer.Builder(context, customMediaSourceFactory).build()\n```\n\n### Java\n\n```java\nExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();\n```\n\n\u003cbr /\u003e\n\nIf your app is using `MediaSource` directly instead of `MediaItem` you should\npass `MediaSource.Factory.UNSUPPORTED` to the `ExoPlayer.Builder` constructor,\nto ensure `DefaultMediaSourceFactory` and `DefaultExtractorsFactory` can be\nstripped by code shrinking. \n\n### Kotlin\n\n```kotlin\nval player = ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build()\nval mediaSource =\n ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)\n .createMediaSource(MediaItem.fromUri(uri))\n```\n\n### Java\n\n```java\nExoPlayer player = new ExoPlayer.Builder(context, MediaSource.Factory.UNSUPPORTED).build();\nProgressiveMediaSource mediaSource =\n new ProgressiveMediaSource.Factory(dataSourceFactory, customExtractorsFactory)\n .createMediaSource(MediaItem.fromUri(uri));\n```\n\n\u003cbr /\u003e"]]