该文章翻译自这里,点击查看英文原文
本指南适用于ExoPlayer 2.x. 如果您仍然使用1.x,您可以在这里找到旧的开发者指南。播放视频和音乐是Android设备上的热门活动。 Android框架提供了MediaPlayer,作为使用最少代码播放媒体的快速解决方案。 它还提供低级媒体API,如MediaCodec,AudioTrack和MediaDrm,可用于构建自定义媒体播放器解决方案。
ExoPlayer是一个开源的应用级媒体播放器,构建在Android的低级媒体API之上。 该开源项目包含ExoPlayer库和一个演示应用程序:
- ExoPlayer库 - 该项目的这一部分包含核心库类。
- Demo app - 这部分项目演示了ExoPlayer的使用。
利弊 与Android内置的MediaPlayer相比,ExoPlayer具有许多优点:
- 支持通过HTTP(DASH)和SmoothStreaming进行动态自适应流,这两种都不受MediaPlayer的支持。 还支持许多其他格式。 有关详细信息,请参阅支持的格式页面。
- 支持高级HLS功能,例如正确处理#EXT-X-DISCONTINUITY标签。
- 能够无缝地合并,连接和循环媒体。
- 自定义和扩展播放器以适应您的用例的能力。 ExoPlayer专门设计了这一点,并允许许多组件被替换为自定义实现。
- 轻松更新播放器与您的应用程序。 因为ExoPlayer是您的应用程序apk中包含的库,所以您可以控制使用哪个版本,您可以轻松地将其更新为常规应用程序更新的一部分。
- 更少的设备具体问题。
- 支持Android 4.4(API等级19)以上的Widevine通用加密。
ExoPlayer的标准音频和视频组件依赖Android的MediaCodec API,这是在Android 4.1(API级别16)中发布的。 因此,它们不适用于早期版本的Android。 Widevine通用加密在Android 4.4(API级别19)及更高版本上可用。
库概览 ExoPlayer库的核心是ExoPlayer接口。 ExoPlayer公开了传统的高级媒体播放器功能,例如缓冲媒体,播放,暂停和寻找的功能。 实施旨在对播放的媒体类型,存储方式和位置及其渲染方式进行少量假设(因此对其进行限制)。 而不是直接实现媒体的加载和渲染,ExoPlayer实现将这项工作委托给创建播放器或播放准备时注入的组件。 所有ExoPlayer实现共同的组件有:
- 一个MediaSource定义了要播放的媒体的,加载媒体,从中可以读取加载的媒体。 MediaSource在播放开始时通过ExoPlayer.prepare注入。
- Render(s)呈现媒体的各个组件。创建播放器时注入渲染器。
- TrackSelector,用于选择由MediaSource提供的轨道,以供每个可用的Render使用。在创建时注入TrackSelector。
- 一个LoadControl,用于控制MediaSource缓冲更多媒体,以及缓冲多少媒体。在创建播放器时注入LoadControl。
在整个库中都存在着实现播放器功能的注入组件的概念。 上面列出的组件的默认实现委派工作到进一步注入的组件中。这使得许多子组件可以用自定义的实现单独替换。例如,默认的MediaSource实现需要通过其构造函数注入一个或多个DataSource工厂。 通过提供定制工厂,则可以从非标准源或不同的网络堆栈加载数据。
入门 对于简单的用例,ExoPlayer入门包括实现以下步骤:
- 添加ExoPlayer作为您项目的依赖。
- 创建一个SimpleExoPlayer实例。
- 将播放器附加到视图(用于视频输出和用户输入)。
- 使用将要播放的MediaSource让播放器准备就绪。
- 播放完成后释放播放器。
添加ExoPlayer作为依赖
开始的第一步是确保您的项目根目录中的build.gradle文件中包含jcenter仓库。
repositories {
jcenter()
}
接下来,为ExoPlayer库添加一个gradle编译依赖关系到应用程序模块的build.gradle文件。
compile 'com.google.android.exoplayer:exoplayer:r2.X.X'
其中r2.X.X是您的首选版本。 有关最新版本,请参阅项目的版本。 有关更多详细信息,请参阅Bintray上的项目。
创建播放器
现在您可以使用ExoPlayerFactory创建一个ExoPlayer实例。 该工厂提供了一系列方法来创建具有不同级别的定制的ExoPlayer实例。 对于绝大多数用例,库中提供的默认Renderer实现就足够了。 对于这种情况,应该使用一个ExoPlayerFactory.newSimpleInstance方法。 这些方法返回SimpleExoPlayer,它扩展了ExoPlayer以添加额外的高级别播放器功能。 以下代码是创建SimpleExoPlayer的示例。
// 1. Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
SimpleExoPlayer player =
ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
将播放器附加到视图
所述ExoPlayer库提供了SimpleExoPlayerView,其封装了PlaybackControlView和在其上的渲染视频的Surface。 SimpleExoPlayerView可以包含在应用程序的布局xml中。 将播放器绑定到视图如下面所示这样简单:
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
如果您需要对播放器控件和渲染视频的Surface进行细粒度控制,则可以分别使用SimpleExoPlayer的
setVideoSurfaceView
,setVideoTextureView
,setVideoSurfaceHolder
和setVideoSurface
方法直接设置播放器的目标SurfaceView,TextureView,SurfaceHolder或Surface。您可以使用PlaybackControlView作为独立组件,或实现与播放器直接交互的自己的播放控件。 setTextOutput
和setId3Output
可用于在播放过程中接收字幕和ID3元数据输出。准备播放器
在ExoPlayer中,每一块媒体均由MediaSource表示。 要播放一块媒体,您必须先创建一个相应的MediaSource,然后将此对象传递给ExoPlayer.prepare。 该ExoPlayer库为DASH MediaSource(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规的媒体文件(ExtractorMediaSource)提供了实现。这些实现将在本指南的后面更详细地描述。 以下代码显示如何使用适合播放MP4文件的MediaSource准备播放器。
// Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "yourApplicationName"), bandwidthMeter);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
dataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
播放器准备好后,可以通过播放器上的方法来控制播放。 例如
setPlayWhenReady
可用于启动和暂停播放,并且可以使用各种seekTo
方法在媒体内查找。 如果播放器被绑定到SimpleExoPlayerView或PlaybackControlView,则用户与这些组件的交互将导致播放器上的相应方法被调用。释放播放器
在不再需要时释放播放器是很重要的,以释放有限的资源,如视频解码器供其他应用使用。 这可以通过调用ExoPlayer.release来完成。
MediaSource 在ExoPlayer中,每一块媒体均由MediaSource表示。 要播放一块媒体,您必须先创建一个相应的MediaSource,然后将此对象传递给ExoPlayer.prepare。 该ExoPlayer库为DASHMediaSource(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规的媒体文件(ExtractorMediaSource)提供了实现,在ExoPlayer演示应用程序中,可以在PlayerActivity中找到实例化所有四个示例。
除了上述的MediaSource实现之外,ExoPlayer库还提供了MergingMediaSource,LoopingMediaSource和ConcatenatingMediaSource。 这些MediaSource实现通过组合实现更复杂的播放功能。 一些常见的用例如下所述。 注意,虽然在视频播放的上下文中描述了以下示例,但它们同样适用于仅音频播放,实际上也适用于任何支持的媒体类型的播放。
此处省略一部分
播放器事件 播放期间,您的应用程序可以监听由ExoPlayer生成的事件,指示播放器的整体状态。 这些事件可用作更新应用用户界面(如播放控件)的触发器。 许多ExoPlayer组件还报告自己的组件特定的低级别事件,这对于性能监视是很有用的。
高层次的事件
ExoPlayer允许使用其
addListener
和removeListener
方法添加和删除ExoPlayer.EventListener的实例。 注册的监听器在播放状态发生变化以及发生导致播放失败的错误时会得到通知。实现自定义播放控件的开发人员应该注册一个监听器,并在播放器的状态发生变化时使用它来更新他们的控件。 如果播放失败,应用程序还应向用户显示适当的错误。
使用SimpleExoPlayer时,可以在播放器上设置其他监听器。 特别地,setVideoListener允许应用程序接收与视频呈现有关的事件,这些事件可能对于调整UI很有用(例如,用来渲染视频的Surface的宽高比)。 可以在SimpleExoPlayer上设置其他侦听器来接收调试信息,例如调用setVideoDebugListener和setAudioDebugListener。
低层次的事件
除了高级别的监听器外,ExoPlayer库提供的许多单独的组件允许自己的事件监听器。 通常需要将Handler对象传递给这些组件,这些组件决定了调用监听器方法的线程。 在大多数情况下,您应该使用与应用程序主线程相关联的Handler。
向组件发送消息
一些ExoPlayer组件允许在播放过程中更改配置。 按照惯例,您可以通过使用
sendMessages
或blockingSendMessages
方法将消息通过ExoPlayer传递到组件来进行这些更改。 这种方法既确保了线程安全性,又能让配置的更改与播放器上执行的任何其他操作一起有序执行。定制 ExoPlayer比Android MediaPlayer主要优点之一是可以自定义和扩展播放器,以更好地适应开发人员的需求。 ExoPlayer库专门设计了这一点,定义了许多接口和抽象基类,使应用程序开发人员可以轻松地替换库提供的默认实现。 以下是构建自定义组件的一些例子:
- Renderer——您可能需要实现自定义的渲染器来处理由库提供的默认实现不支持的媒体类型。
- Extractor——如果您需要支持库当前不支持的容器格式,请考虑实现自定义Extractor类,然后可以将其与ExtractorMediaSource一起使用以播放该类型的媒体。
- MediaSource——如果希望获取媒体样本然后以自定义方式提供给渲染器,或者您希望实现自定义的MediaSource合成行为,则适合实现自定义MediaSource类。
- TrackSelector——实现自定义TrackSelector允许应用程序开发人员更改MediaSource所公开的轨道被选中以供每个可用渲染器使用的方式。
- DataSource - ExoPlayer的上层包已经包含了不同用例下的一些DataSource实现。您可能希望实现您自己的DataSource类以通过其他方式加载数据,例如通过自定义协议,使用自定义HTTP堆栈或通过持久缓存。
- 如果自定义组件需要将事件报告回应用程序,我们建议您使用与现有ExoPlayer组件相同的模型,其中将事件侦听器与Handler一起传递到组件的构造函数。
- 我们建议自定义组件使用与现有ExoPlayer组件相同的模型,如向组件发送消息中所述,以便在播放过程中由应用重新配置。 为此,您应该实现一个ExoPlayerComponent并在其handleMessage方法中接收配置的更改。 您的应用程序应通过调用ExoPlayer的sendMessages和blockingSendMessages方法来传递配置的更改。
ExoPlayer库提供了一个名为DefaultDrmSessionManager的DrmSessionManager的默认实现,它使用MediaDrm。 会话管理器支持在设备上存在模块化DRM组件的任何DRM方案。 所有Android设备都需要支持Widevine模块化DRM(具有L3安全性,尽管许多设备也支持L1)。 某些设备可能支持其他方案,如PlayReady。 所有Android TV设备都支持PlayReady。
【Android开发|Exoplayer Developer guide官方文档译文】ExoPlayer演示应用程序中的PlayerActivity演示了如何在实例化播放器时创建和注入DrmSessionManager。
推荐阅读
- 从零开发一个完整的Android项目(九)——图片浏览
- Android开发|ViewPager自适应高度问题
- Android|Android 指定销毁一个Activity
- 【Android】简单图片浏览器
- 理解ButterKnife(自动生成绑定资源的代码)
- MAC下搭建Android Studio
- NestedScrollingParent 和NestedScrollingChild 实现嵌套滑动
- android用shape画一条横线
- 华为推送 的坑
- Duplicate class com.alipay.a.a.a found in modules classes.jar (:alipaySdk-15.6.2-20190416165036:) an