版权声明:本文为博主原创文章,转载请注明出处。 推荐: 欢迎关注我创建的Android TV 简书专题,会定期给大家分享一些AndroidTV相关的内容:Android TV
前言:ExoPlayer是google推出的一个应用级的播放框架。接下来我来对它做一个简单的介绍。 ###一,为什么是ExoPlayer? 1.支持更多的格式 我们知道Android 提供的mediaPlayer只支持有限的格式,比如视频,它支持MP4,3GP。想要播放其他格式的视频还要进行相应的转换。ExoPlayer提供了强大的格式支持。 ExoPlayer支持的媒体格是在多个级别定义的。 从最低层到最高层,分别是:
- 单个媒体样本的格式(例如,视频帧或音频帧)。 我们称这些样本格式 。 请注意,典型的视频文件将包含至少两种样本格式的媒体; 一个用于视频(例如,H.264)和一个用于音频(例如,AAC)。
- 容纳媒体样本和相关元数据的容器的格式。 我们称这些容器格式 。 媒体文件具有单个容器格式(例如MP4),通常由文件扩展名指示。 请注意,对于某些仅音频格式(例如MP3),样本和容器格式可能相同。
- 自适应流技术,如DASH,SmoothStreaming和HLS。 这些不是媒体格式,但是仍然需要定义什么级别的支持ExoPlayer提供。
2.ExoPlayer是java语言编写的,相比与MediaPlayer用Native Code来说,可以更清楚的获得一些异常源和进行部分代码调试。 3.ExoPlayer是开源的,github上地址ExoPlayer遇到问题后可以提交Issues,最近遇到关于SimpleExoPlayer setVideoListener去监听OnVideoSizeChanged()时黑屏有声音,然后提交了一个Issues:The surface show nothing after mSimpleExoPlayer.setVideoListener(mVideoListener),他们很快给了回复,另外开源的代码经过大家的验证,也会更加的健壮。 4.ExoPlayer有强大的开发文档developer guide ,读者也可以根据文档更好的了解它。 ###二,如何使用? 这里演示一个播放器的简单使用。 ####1.在xml中
- <LinearLayout
- android:id="@+id/activity_main"
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context="com.songwenju.useexoplayer.MainActivity">
-
- <com.google.android.exoplayer2.ui.SimpleExoPlayerView
- android:id="@+id/exoView"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ProgressBar
- android:id="@+id/progressBar"
- android:visibility="gone"
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"/>
- </com.google.android.exoplayer2.ui.SimpleExoPlayerView>
- </LinearLayout>
-
- 复制代码
这里使用了SimpleExoPlayerView,在其内部添加了一个ProgressBar。 ####2.播放需要的步骤 初始化播放器:
- /**
- * 初始化player
- */
- private void initPlayer() {
- //1. 创建一个默认的 TrackSelector
- BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
- TrackSelection.Factory videoTackSelectionFactory =
- new AdaptiveTrackSelection.Factory(bandwidthMeter);
- TrackSelector trackSelector =
- new DefaultTrackSelector(videoTackSelectionFactory);
- LoadControl loadControl = new DefaultLoadControl();
- //2.创建ExoPlayer
- mSimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector,loadControl);
- //3.创建SimpleExoPlayerView
- mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoView);
- //4.为SimpleExoPlayer设置播放器
- mExoPlayerView.setPlayer(mSimpleExoPlayer);
- }
-
- 复制代码
开始播放:
- private void playVideo() {
- //测量播放过程中的带宽。 如果不需要,可以为null。
- DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
- // 生成加载媒体数据的DataSource实例。
- DataSource.Factory dataSourceFactory
- = new DefaultDataSourceFactory(MainActivity.this,
- Util.getUserAgent(MainActivity.this,"useExoplayer"),bandwidthMeter);
- // 生成用于解析媒体数据的Extractor实例。
- ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
-
-
- // MediaSource代表要播放的媒体。
- MediaSource videoSource = new ExtractorMediaSource(playerUri,dataSourceFactory,extractorsFactory,
- null,null);
- //Prepare the player with the source.
- mSimpleExoPlayer.prepare(videoSource);
- //添加监听的listener
- // mSimpleExoPlayer.setVideoListener(mVideoListener);
- mSimpleExoPlayer.addListener(eventListener);
- // mSimpleExoPlayer.setTextOutput(mOutput);
- mSimpleExoPlayer.setPlayWhenReady(true);
-
- }
- 复制代码
监听播放器的状态:
- private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
- @Override
- public void onTimelineChanged(Timeline timeline, Object manifest) {
- LogUtil.i(this,"onTimelineChanged");
- }
-
- @Override
- public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
- LogUtil.i(this,"onTracksChanged");
- }
-
- @Override
- public void onLoadingChanged(boolean isLoading) {
- LogUtil.i(this,"onLoadingChanged");
- }
-
- @Override
- public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
- LogUtil.i(this,"onPlayerStateChanged: playWhenReady = "+String.valueOf(playWhenReady)
- +" playbackState = "+playbackState);
- switch (playbackState){
- case ExoPlayer.STATE_ENDED:
- LogUtil.i(this,"Playback ended!");
- //Stop playback and return to start position
- setPlayPause(false);
- mSimpleExoPlayer.seekTo(0);
- break;
- case ExoPlayer.STATE_READY:
- mProgressBar.setVisibility(View.GONE);
- LogUtil.i(this,"ExoPlayer ready! pos: "+mSimpleExoPlayer.getCurrentPosition()
- +" max: "+stringForTime((int)mSimpleExoPlayer.getDuration()));
- setProgress(0);
- break;
- case ExoPlayer.STATE_BUFFERING:
- LogUtil.i(this,"Playback buffering!");
- mProgressBar.setVisibility(View.VISIBLE);
- break;
- case ExoPlayer.STATE_IDLE:
- LogUtil.i(this,"ExoPlayer idle!");
- break;
- }
- }
-
- @Override
- public void onPlayerError(ExoPlaybackException error) {
- LogUtil.i(this,"onPlaybackError: "+error.getMessage());
- }
-
- @Override
- public void onPositionDiscontinuity() {
- LogUtil.i(this,"onPositionDiscontinuity");
- }
-
- @Override
- public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
- LogUtil.i(this,"MainActivity.onPlaybackParametersChanged."+playbackParameters.toString());
- }
- };
- 复制代码
- mSimpleExoPlayer.addListener(eventListener);
- 复制代码
通过监听状态去显示loading条,做错误处理等。
Activity退出时,释放播放器:
- @Override
- protected void onPause() {
- LogUtil.i(this,"MainActivity.onPause.");
- super.onPause();
- mSimpleExoPlayer.stop();
- }
-
- @Override
- protected void onStop() {
- LogUtil.i(this,"MainActivity.onStop.");
- super.onStop();
- mSimpleExoPlayer.release();
- }
- 复制代码
MainActivity完整的代码
- public class MainActivity extends AppCompatActivity {
- private SimpleExoPlayerView mExoPlayerView;
- private SimpleExoPlayer mSimpleExoPlayer;
- private Context mContext;
- Uri playerUri = Uri.parse("https://storage.googleapis.com/android-tv/Sample%20videos/Demo%20Slam/Google%20Demo%20Slam_%20Hangin'%20with%20the%20Google%20Search%20Bar.mp4");
- private ProgressBar mProgressBar;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- setContentView(R.layout.activity_main);
- mContext = this;
- mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
- initPlayer();
- playVideo();
-
- }
-
- /**
- * 初始化player
- */
- private void initPlayer() {
- //1. 创建一个默认的 TrackSelector
- BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
- TrackSelection.Factory videoTackSelectionFactory =
- new AdaptiveTrackSelection.Factory(bandwidthMeter);
- TrackSelector trackSelector =
- new DefaultTrackSelector(videoTackSelectionFactory);
- LoadControl loadControl = new DefaultLoadControl();
- //2.创建ExoPlayer
- mSimpleExoPlayer = ExoPlayerFactory.newSimpleInstance(this,trackSelector,loadControl);
- //3.创建SimpleExoPlayerView
- mExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.exoView);
- //4.为SimpleExoPlayer设置播放器
- mExoPlayerView.setPlayer(mSimpleExoPlayer);
- }
-
- private void playVideo() {
- //测量播放过程中的带宽。 如果不需要,可以为null。
- DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
- // 生成加载媒体数据的DataSource实例。
- DataSource.Factory dataSourceFactory
- = new DefaultDataSourceFactory(MainActivity.this,
- Util.getUserAgent(MainActivity.this,"useExoplayer"),bandwidthMeter);
- // 生成用于解析媒体数据的Extractor实例。
- ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
-
-
- // MediaSource代表要播放的媒体。
- MediaSource videoSource = new ExtractorMediaSource(playerUri,dataSourceFactory,extractorsFactory,
- null,null);
- //Prepare the player with the source.
- mSimpleExoPlayer.prepare(videoSource);
- //添加监听的listener
- // mSimpleExoPlayer.setVideoListener(mVideoListener);
- mSimpleExoPlayer.addListener(eventListener);
- // mSimpleExoPlayer.setTextOutput(mOutput);
- mSimpleExoPlayer.setPlayWhenReady(true);
-
- }
-
-
- TextRenderer.Output mOutput = new TextRenderer.Output() {
- @Override
- public void onCues(List<Cue> cues) {
- LogUtil.i(this,"MainActivity.onCues.");
- }
- };
-
- private SimpleExoPlayer.VideoListener mVideoListener = new SimpleExoPlayer.VideoListener() {
- @Override
- public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
- LogUtil.i(this,"MainActivity.onVideoSizeChanged.width:"+width+", height:"+height);
-
- }
-
- @Override
- public void onRenderedFirstFrame() {
- LogUtil.i(this,"MainActivity.onRenderedFirstFrame.");
- }
- };
-
-
- private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
- @Override
- public void onTimelineChanged(Timeline timeline, Object manifest) {
- LogUtil.i(this,"onTimelineChanged");
- }
-
- @Override
- public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
- LogUtil.i(this,"onTracksChanged");
- }
-
- @Override
- public void onLoadingChanged(boolean isLoading) {
- LogUtil.i(this,"onLoadingChanged");
- }
-
- @Override
- public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
- LogUtil.i(this,"onPlayerStateChanged: playWhenReady = "+String.valueOf(playWhenReady)
- +" playbackState = "+playbackState);
- switch (playbackState){
- case ExoPlayer.STATE_ENDED:
- LogUtil.i(this,"Playback ended!");
- //Stop playback and return to start position
- setPlayPause(false);
- mSimpleExoPlayer.seekTo(0);
- break;
- case ExoPlayer.STATE_READY:
- mProgressBar.setVisibility(View.GONE);
- LogUtil.i(this,"ExoPlayer ready! pos: "+mSimpleExoPlayer.getCurrentPosition()
- +" max: "+stringForTime((int)mSimpleExoPlayer.getDuration()));
- setProgress(0);
- break;
- case ExoPlayer.STATE_BUFFERING:
- LogUtil.i(this,"Playback buffering!");
- mProgressBar.setVisibility(View.VISIBLE);
- break;
- case ExoPlayer.STATE_IDLE:
- LogUtil.i(this,"ExoPlayer idle!");
- break;
- }
- }
-
- @Override
- public void onPlayerError(ExoPlaybackException error) {
- LogUtil.i(this,"onPlaybackError: "+error.getMessage());
- }
-
- @Override
- public void onPositionDiscontinuity() {
- LogUtil.i(this,"onPositionDiscontinuity");
- }
-
- @Override
- public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
- LogUtil.i(this,"MainActivity.onPlaybackParametersChanged."+playbackParameters.toString());
- }
- };
-
- /**
- * Starts or stops playback. Also takes care of the Play/Pause button toggling
- * @param play True if playback should be started
- */
- private void setPlayPause(boolean play){
- mSimpleExoPlayer.setPlayWhenReady(play);
- }
-
- private String stringForTime(int timeMs) {
- StringBuilder mFormatBuilder;
- Formatter mFormatter;
- mFormatBuilder = new StringBuilder();
- mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
- int totalSeconds = timeMs / 1000;
-
- int seconds = totalSeconds % 60;
- int minutes = (totalSeconds / 60) % 60;
- int hours = totalSeconds / 3600;
-
- mFormatBuilder.setLength(0);
- if (hours > 0) {
- return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
- } else {
- return mFormatter.format("%02d:%02d", minutes, seconds).toString();
- }
- }
-
- @Override
- protected void onPause() {
- LogUtil.i(this,"MainActivity.onPause.");
- super.onPause();
- mSimpleExoPlayer.stop();
- }
-
- @Override
- protected void onStop() {
- LogUtil.i(this,"MainActivity.onStop.");
- super.onStop();
- mSimpleExoPlayer.release();
- }
- }
-
- 复制代码
gitHub实例:useExoPlayer。 关注微信公众号,定期为你推荐移动开发相关文章。