点击下载demo
横屏效果
package qingyunbomei.com.xingtest.videos;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.TextureView;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import butterknife.BindView;
import butterknife.ButterKnife;
import qingyunbomei.com.xingtest.R;
import qingyunbomei.com.xingtest.utils.PixelUtil;
import qingyunbomei.com.xingtest.utils.TimeUtils;
public class VideoActivity extends AppCompatActivity {
@BindView(R.id.simpleExoPlayerView)
SimpleExoPlayerView simpleExoPlayerView;
@BindView(R.id.texture_view)
TextureView textureView;
@BindView(R.id.start_play)
ImageView startPlay;
@BindView(R.id.already_player_time)
TextView alreadyPlayerTime;
@BindView(R.id.seek_bar)
SeekBar seekBar;
@BindView(R.id.all_player_time)
TextView allPlayerTime;
@BindView(R.id.all_screen)
ImageView allScreen;
@BindView(R.id.constraintLayout)
ConstraintLayout constraintLayout;
@BindView(R.id.play_linear)
LinearLayout playLinear;
private static final int UP_TIME = 0;//更新播放时间
private boolean screenFlag = false;//全屏标记
private SimpleExoPlayer player;
private boolean playFlag = false;//播放状态
private ExecutorService executors = Executors.newSingleThreadExecutor();
private final MyHandler myHandler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
ButterKnife.bind(this);
initVideo();
}
//初始化视频
private void initVideo() {
//create a TrackSelector 选择MediaSource
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
//从MediaSource中选出media提供给可用的Render S来渲染,在创建播放器时被注入
TrackSelection.Factory videoTrackSelectionFactor = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactor);
//Create a default LoadControl 控制MediaSource缓存media
LoadControl loadControl = new DefaultLoadControl();
//Create the player
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
//produces DataSource instances through which media data is loaded
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "飞星"), bandwidthMeter);
//Produces Extractor instances for parsing the media data 萃取剂
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource videoSource = new ExtractorMediaSource(Uri.parse("http://w5.dwstatic.com/54/3/1622/2166193-100-1464903053.mp4"),
dataSourceFactory, extractorsFactory, null, null);
//设置资源
player.prepare(videoSource);
//显示字幕
// player.setTextOutput(new TextRenderer.Output() {
// @Override
// public void onCues(List cues) {
//
// }
// });
player.addListener(eventListener);
player.setVideoTextureView(textureView);
// simpleExoPlayerView.setPlayer(player);
}
//播放事件监听
private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener()
{
@Override
public void onTimelineChanged(Timeline timeline, Object manifest)
{
System.out.println("播放: onTimelineChanged 周期总数 " + timeline);
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
System.out.println("播放: TrackGroupArray ");
}
@Override
public void onLoadingChanged(boolean isLoading) {
System.out.println("播放: onLoadingChanged " + TimeUtils.secToTime((int) (player.getBufferedPosition() / 1000)));
//设置二级进度条
seekBar.setSecondaryProgress((int) (player.getBufferedPosition() / 1000));
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case PlaybackState.STATE_PLAYING:
//初始化播放点击事件并设置总时长
initPlayVideo();
System.out.println("播放状态: 准备 playing");
break;
case PlaybackState.STATE_BUFFERING:
System.out.println("播放状态: 缓存完成 playing");
break;
case PlaybackState.STATE_CONNECTING:
System.out.println("播放状态: 连接 CONNECTING");
break;
case PlaybackState.STATE_ERROR://错误
System.out.println("播放状态: 错误 STATE_ERROR");
break;
case PlaybackState.STATE_FAST_FORWARDING:
System.out.println("播放状态: 快速传递");
pausePlay();//暂停播放
break;
case PlaybackState.STATE_NONE:
System.out.println("播放状态: 无 STATE_NONE");
break;
case PlaybackState.STATE_PAUSED:
System.out.println("播放状态: 暂停 PAUSED");
break;
case PlaybackState.STATE_REWINDING:
System.out.println("播放状态: 倒回 REWINDING");
break;
case PlaybackState.STATE_SKIPPING_TO_NEXT:
System.out.println("播放状态: 跳到下一个");
break;
case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
System.out.println("播放状态: 跳到上一个");
break;
case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM:
System.out.println("播放状态: 跳到指定的Item");
break;
case PlaybackState.STATE_STOPPED:
System.out.println("播放状态: 停止的 STATE_STOPPED");
break;
}
}
@Override
public void onPlayerError(ExoPlaybackException error) {
System.out.println("播放: onPlayerError ");
}
@Override
public void onPositionDiscontinuity() {
System.out.println("播放: onPositionDiscontinuity ");
}
};
//初始化播放事件
private void initPlayVideo()
{
allPlayerTime.setText(TimeUtils.secToTime((int) (player.getDuration() / 1000)));
//设置总时长
seekBar.setMax((int) (player.getDuration() / 1000));
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { }
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//是暂停的开始播放
if (!player.getPlayWhenReady()) {
continuePlay();//继续播放
}
player.seekTo(seekBar.getProgress() * 1000);
}
});
//播放按钮
startPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (player.getPlayWhenReady()) {
pausePlay();//暂停播放
} else {
continuePlay();//继续播放
}
}
});
//全屏切换
allScreen.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
if (screenFlag)//是全屏
{
setHalfScreen();
} else {
screenFlag = true;//设置为全屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//设置控件大小
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) textureView.getLayoutParams();
params.width = ConstraintLayout.LayoutParams.MATCH_PARENT;
System.out.println("屏幕: 控件 : " + constraintLayout.getHeight());
params.height = getHeight();
params.dimensionRatio = 0f;
playLinear.setPadding(0,0,0, PixelUtil.dp2px(VideoActivity.this,25));
textureView.setLayoutParams(params);
}
}
});
}
//设置为半屏
private void setHalfScreen()
{
screenFlag = false;//设置为半屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//设置控件大小
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) textureView.getLayoutParams();
params.width = ConstraintLayout.LayoutParams.MATCH_PARENT;
params.dimensionRatio = 1.6f;
playLinear.setPadding(0,0,0,0);
textureView.setLayoutParams(params);
}
//暂停播放
private void pausePlay() {
player.setPlayWhenReady(false);
startPlay.setBackgroundColor(Color.WHITE);
playFlag = false;
}
//继续播放
private void continuePlay()
{
player.setPlayWhenReady(true);
startPlay.setBackgroundColor(Color.RED);
//开始读取进度
playFlag = true;
executors.execute(runnable);
}
private static class MyHandler extends Handler
{
private final WeakReference mActivity;
private MyHandler(VideoActivity mActivity)
{
this.mActivity = new WeakReference<>(mActivity);
}
@Override
public void handleMessage(Message msg) {
if (mActivity.get() == null)
{
return;
}
if (msg.what == UP_TIME) {
//设置播放进度
VideoActivity videoActivity = mActivity.get();
videoActivity.seekBar.setProgress(msg.arg1);
videoActivity.alreadyPlayerTime.setText(TimeUtils.secToTime(msg.arg1));
}
}
}
//开启线程读取进度
private Runnable runnable = new Runnable() {
@Override
public void run() {
while (playFlag) {
Message msg = new Message();
msg.what = UP_TIME;
//获取播放时间
msg.arg1 = (int) (player.getCurrentPosition() / 1000);
myHandler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
//释放资源
if (player != null) {
playFlag = false;//停止线程
executors.shutdown();
player.stop();
player.release();
player = null;
}
myHandler.removeCallbacksAndMessages(null);
}
//获取屏幕高度
private int getHeight() {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK &&
getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
{
//设置半屏
setHalfScreen();
}
return super.onKeyDown(keyCode, event);
}
}