ExoPlayer介绍:
https://google.github.io/ExoPlayer/supported-formats.html
https://codelabs.developers.google.com/codelabs/exoplayer-intro/#0
https://blog.csdn.net/hejjunlin/article/details/54693696
截图


对PlayerView的封装
import android.annotation.SuppressLint;
import android.content.Context;
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
import static com.google.android.exoplayer2.ui.AspectRatioFrameLayout.RESIZE_MODE_FILL;
/**
* @author: fanrunqi
* @date: 2018/10/19 16:20
*/
public class TheExoPlayer extends PlayerView {
private ExoPlayer player;
private boolean isPlay;
private OnStateListener onStateListener;
private boolean isLoopProgress = true;
private boolean isPause;
private Player.EventListener eventListener;
public TheExoPlayer(Context context) {
this(context, null);
}
public TheExoPlayer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TheExoPlayer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setResizeMode(RESIZE_MODE_FILL);
setUseController(false);
player = ExoPlayerFactory.newSimpleInstance(getContext());
setPlayer(player);
player.addListener(eventListener=new Player.EventListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
if (onStateListener != null) {
onStateListener.onLoadingChanged(isLoading);
}
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == PlaybackState.STATE_PLAYING) {
if (onStateListener != null) {
onStateListener.onPlayPrepare();
handler.postDelayed(task, 1000);
}
}
}
});
}
public void initialization(String applicationName, String videoUrl) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(),
Util.getUserAgent(getContext(), applicationName));
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(videoUrl));
player.prepare(videoSource);
player.setRepeatMode(REPEAT_MODE_ALL);
}
@Override
public void onResume() {
super.onResume();
hideSystemUi();
if(isPause){
isPause=false;
play();
}
}
public void onPause() {
if (isPlay) {
isPause=true;
player.setPlayWhenReady(false);
isPlay = false;
}
}
public void onDestroy() {
isLoopProgress = false;
if(null!=eventListener){
player.removeListener(eventListener);
}
if (player != null) {
player.release();
player = null;
}
}
public void play() {
if (!isPlay) {
player.setPlayWhenReady(true);
isPlay = true;
}
}
public void pause() {
if (isPlay) {
player.setPlayWhenReady(false);
isPlay = false;
}
}
public void seekTo(int progress) {
if (player != null) {
player.seekTo(progress * 1000);
}
}
public boolean isPlaying() {
return isPlay;
}
public String getCurrentTime() {
return secToTime((int) (player.getCurrentPosition() / 1000));
}
public String getVideoTotalTime() {
return secToTime(getVideoTotalSeconds());
}
public int getBufferedProgress() {
return (int) (player.getBufferedPosition() / 1000);
}
public int getCurrentProgress() {
return (int) (player.getCurrentPosition() / 1000);
}
public int getVideoTotalSeconds() {
return (int) (player.getContentDuration() / 1000);
}
public String secToTime(int time) {
int day;
int hour;
int minute;
int second;
if (time <= 0) {
return "00:00";
} else {
minute = time / 60;
if (minute < 60) {
second = time % 60;
return unitFormat(minute) + ":" + unitFormat(second) + "";
}
hour = minute / 60;
if (hour < 24) {
minute = minute % 60;
second = time - hour * 3600 - minute * 60;
return unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second) + ":";
}
day = hour / 24;
hour = hour % 24;
minute = minute - day * 24 * 60 - hour * 60;
return unitFormat(day) + "天" + unitFormat(hour) + "小时" + unitFormat(minute) + "分钟";
}
}
private String unitFormat(int i) {
String retStr;
if (i >= 0 && i < 10)
retStr = "0" + Integer.toString(i);
else
retStr = "" + i;
return retStr;
}
private Handler handler = new Handler();
private Runnable task = new Runnable() {
public void run() {
if (player != null) {
onStateListener.onProgressChanged(getCurrentProgress());
}
if (isLoopProgress) {
handler.postDelayed(this, 1000);
}
}
};
@SuppressLint("InlinedApi")
private void hideSystemUi() {
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
public void setOnStateListener(OnStateListener listener) {
onStateListener = listener;
}
public interface OnStateListener {
void onLoadingChanged(boolean isLoading);
void onPlayPrepare();
void onProgressChanged(int progress);
}
}
对TheExoPlayer的使用
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import cn.leo.androidvideoplayer.R;
/**
* @author: fanrunqi
* @date: 2018/10/19 19:30
*/
public class TheExoPlayerUse extends RelativeLayout {
TheExoPlayer playerView;
TextView begin,end;
SeekBar seekBar;
ImageView play_pause;
public TheExoPlayerUse(Context context) {
this(context, null);
init();
}
public TheExoPlayerUse(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init();
}
public TheExoPlayerUse(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayoutInflater from = LayoutInflater.from(getContext());
View view = from.inflate(R.layout.e_video_view, null);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
view.setLayoutParams(rlp);
playerView = view.findViewById(R.id.video_view);
begin = view.findViewById(R.id.tv_begin);
end = view.findViewById(R.id.tv_end);
seekBar = view.findViewById(R.id.seekBar);
play_pause = view.findViewById(R.id.play_pause);
playerView.setOnStateListener(new TheExoPlayer.OnStateListener() {
@Override
public void onLoadingChanged(boolean isLoading) {
seekBar.setSecondaryProgress(playerView.getBufferedProgress());
}
@Override
public void onPlayPrepare() {
initPlayVideo();
}
@Override
public void onProgressChanged(int progress) {
begin.setText(playerView.getCurrentTime());
seekBar.setProgress(progress);
}
});
addView(view);
}
public void load(String applicationName, String videoUrl) {
playerView.initialization(applicationName,videoUrl);
}
private void initPlayVideo() {
play_pause.setOnClickListener(v -> {
if(playerView.isPlaying()){
playerView.pause();
play_pause.setBackgroundResource(R.drawable.play);
}else {
playerView.play();
play_pause.setBackground(null);
}
});
end.setText(playerView.getVideoTotalTime());
seekBar.setMax(playerView.getVideoTotalSeconds());
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) {
playerView.play();
playerView.seekTo(seekBar.getProgress());
play_pause.setBackground(null);
}
});
}
public void onResume() {
playerView.onResume();
}
public void onPause() {
playerView.onPause();
}
public void onDestroy() {
playerView.onDestroy();
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<cn.leo.androidvideoplayer.lib.TheExoPlayer
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ImageView
android:background="@drawable/play"
android:id="@+id/play_pause"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_begin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:text="00:00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<SeekBar
android:id="@+id/seekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv_end"
app:layout_constraintStart_toEndOf="@+id/tv_begin" />
<TextView
android:id="@+id/tv_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:text="05:00"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</android.support.constraint.ConstraintLayout>
主界面
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import cn.leo.androidvideoplayer.lib.TheExoPlayerUse;
public class MainActivity extends AppCompatActivity {
TheExoPlayerUse theExoPlayerUse;
String url = "https://media.w3.org/2010/05/sintel/trailer.mp4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(v ->
startActivity(new Intent(MainActivity.this, SecondActivity.class)));
theExoPlayerUse = findViewById(R.id.eVideoView);
theExoPlayerUse.load("AndroidVideoPlayer", url);
}
@Override
protected void onResume() {
super.onResume();
theExoPlayerUse.onResume();
}
@Override
protected void onPause() {
super.onPause();
theExoPlayerUse.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
theExoPlayerUse.onDestroy();
}
}
网友评论