APK 축소
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
APK 크기를 최소화하는 것은 우수한 Android 앱을 개발하는 데 중요한 측면입니다. 특히 개발 시장을 타겟팅할 때와 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 콘텐츠를 재생하는 앱의 경우 코드 축소를 사용 설정하면 APK 크기에 대한 ExoPlayer의 기여도를 약 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()
자바
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)가 플레이어에 의해 처리되거나 내보내지지 않습니다.
기본적으로 플레이어는 DefaultExtractorsFactory
를 사용하여 프로그레시브 미디어를 재생하기 위해 Extractor
인스턴스를 만듭니다. DefaultExtractorsFactory
는 ExoPlayer 라이브러리에 제공된 모든 Extractor
구현에 종속되므로 코드 축소로 인해 삭제되지 않습니다. 앱이 소수의 컨테이너 형식만 재생해야 하거나 프로그레시브 미디어를 전혀 재생하지 않는 것을 알고 있다면 대신 자체 ExtractorsFactory
를 지정할 수 있습니다. 예를 들어 mp4 파일만 재생하면 되는 앱은 다음과 같은 팩토리를 제공할 수 있습니다.
Kotlin
val mp4ExtractorFactory = ExtractorsFactory {
arrayOf<Extractor>(Mp4Extractor(DefaultSubtitleParserFactory()))
}
val player =
ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, mp4ExtractorFactory)).build()
자바
ExtractorsFactory mp4ExtractorFactory =
() -> new Extractor[] {new Mp4Extractor(new DefaultSubtitleParserFactory())};
ExoPlayer player =
new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, mp4ExtractorFactory))
.build();
이렇게 하면 코드 축소로 다른 Extractor
구현을 삭제할 수 있으므로 크기가 크게 줄어들 수 있습니다.
앱에서 프로그레시브 콘텐츠가 전혀 재생되지 않는 경우 DefaultMediaSourceFactory
생성자에 ExtractorsFactory.EMPTY
를 전달한 다음 ExoPlayer.Builder
생성자에 해당 mediaSourceFactory
를 전달해야 합니다.
Kotlin
val player =
ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, ExtractorsFactory.EMPTY)).build()
자바
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()
자바
ExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();
앱에서 MediaItem
대신 MediaSource
를 직접 사용하는 경우 DefaultMediaSourceFactory
및 DefaultExtractorsFactory
가 코드 축소에 의해 삭제될 수 있도록 MediaSource.Factory.UNSUPPORTED
를 ExoPlayer.Builder
생성자에 전달해야 합니다.
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));
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-08-27(UTC)
[[["이해하기 쉬움","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(UTC)"],[],[],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"]]