尽可能减小 APK 大小是开发优质 Android 应用的一个重要方面。在面向发展中市场进行开发时,以及在开发 Android 即时应用时,这一点尤其重要。对于此类情况,最好尽可能减小 APK 中包含的 ExoPlayer 库的大小。本页简要介绍了有助于实现此目标的一些简单步骤。
仅使用必需的依赖项
仅依赖于您实际需要的库模块。例如,以下代码将添加对 ExoPlayer、DASH 和界面库模块的依赖项,这可能是仅播放 DASH 内容的应用所需要的:
Kotlin
implementation("androidx.media3:media3-exoplayer:1.10.1")
implementation("androidx.media3:media3-exoplayer-dash:1.10.1")
implementation("androidx.media3:media3-ui:1.10.1")
Groovy
implementation "androidx.media3:media3-exoplayer:1.10.1"
implementation "androidx.media3:media3-exoplayer-dash:1.10.1"
implementation "androidx.media3:media3-ui:1.10.1"
启用代码和资源缩减功能
您应为应用的发布 build 启用代码和资源缩减功能。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));