APK の圧縮

APK サイズを最小限に抑えることは、優れた Android アプリを開発するうえで重要な要素です。これは、新興市場をターゲットとする場合や、Android インスタント アプリを開発する場合に特に当てはまります。このような場合、APK に含まれる ExoPlayer ライブラリのサイズを最小限に抑えることが望ましいことがあります。このページでは、それを実現するための簡単な手順を説明します。

必要な依存関係のみを使用する

実際に必要なライブラリ モジュールのみに依存します。たとえば、DASH コンテンツのみを再生するアプリに必要な場合、次のように ExoPlayer、DASH、UI ライブラリ モジュールへの依存関係を追加します。

Kotlin

implementation("androidx.media3:media3-exoplayer:1.7.1")
implementation("androidx.media3:media3-exoplayer-dash:1.7.1")
implementation("androidx.media3:media3-ui:1.7.1")

Groovy

implementation "androidx.media3:media3-exoplayer:1.7.1"
implementation "androidx.media3:media3-exoplayer-dash:1.7.1"
implementation "androidx.media3:media3-ui:1.7.1"

コードとリソースの圧縮を有効にする

アプリのリリースビルドでコードとリソースの圧縮を有効にする必要があります。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()

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 など)はプレーヤーによって処理または出力されません)。

アプリに必要なエクストラクタを指定する

デフォルトでは、プレーヤーは DefaultExtractorsFactory を使用してプログレッシブ メディアを再生するために Extractor インスタンスを作成します。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 実装を削除できるようになり、サイズを大幅に削減できます。

アプリでプログレッシブ コンテンツがまったく再生されない場合は、DefaultMediaSourceFactory コンストラクタに ExtractorsFactory.EMPTY を渡し、その mediaSourceFactoryExoPlayer.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 のインスタンス化

アプリでカスタム MediaSource.Factory を使用しており、コード ストリッピングで DefaultMediaSourceFactory を削除したい場合は、MediaSource.FactoryExoPlayer.Builder コンストラクタに直接渡す必要があります。

Kotlin

val player = ExoPlayer.Builder(context, customMediaSourceFactory).build()

Java

ExoPlayer player = new ExoPlayer.Builder(context, mediaSourceFactory).build();

アプリで MediaItem ではなく MediaSource を直接使用している場合は、ExoPlayer.Builder コンストラクタに MediaSource.Factory.UNSUPPORTED を渡して、コード圧縮で DefaultMediaSourceFactoryDefaultExtractorsFactory を確実に削除できるようにする必要があります。

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));