最小化 APK 大小是开发优秀 Android 应用的重要方面。这在面向发展中市场以及开发 Android 即时应用时尤其重要。在这种情况下,最好将 APK 中包含的 ExoPlayer 库大小最小化。本页面概述了一些有助于实现此目的的简单步骤。
仅使用必需的依赖项
仅依赖您实际需要的库模块。例如,以下代码将添加对 ExoPlayer、DASH 和 UI 库模块的依赖项,这可能是仅播放 DASH 内容的应用所必需的
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 内容的应用,通过启用代码缩减,可以将 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))。
指定您的应用需要哪些提取器
默认情况下,播放器使用 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
实现通过代码缩减被移除,从而显著减小大小。
如果您的应用根本不播放渐进式内容,您应该将 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 实例化
如果您的应用正在使用自定义的 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));