如果项目中需要用到视频播放功能,android原生的视频播放器坑实在太多了。所以介绍一个好用的第三方播放器,可自定义多种效果(如播放回调、缓冲动画等)。简单靠谱,不多废话,直接看代码。
1、首先添加依赖
implementation 'com.linsea:universalvideoview:1.1.0@aar'
2、然后就是layout布局文件,我这里首先是定义了一个半屏的效果
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:padding="5dp"
android:src="@mipmap/icon_back"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<FrameLayout
android:id="@+id/video_layout"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:background="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.universalvideoview.UniversalVideoView
android:id="@+id/videoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
app:uvv_autoRotation="true"
app:uvv_fitXY="false"/>
<com.universalvideoview.UniversalMediaController
android:id="@+id/media_controller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:uvv_scalable="true"/>
</FrameLayout>
3、接下来就是Activity中的应用了
public class VideoPlayActivity extends BaseActivity implements UniversalVideoView.VideoViewCallback {
private static final String KEY_VIDEO_URL = "video_url";
private static final String KEY_VIDEO_TITLE = "video_title";
private static final String SEEK_POSITION_KEY = "SEEK_POSITION_KEY";
//播放器
UniversalVideoView mVideoView;
//进度条等
UniversalMediaController mMediaController;
//返回按钮
private ImageView ivBack;
View mVideoLayout;
private int mSeekPosition;//进度
private int cachedHeight;
private boolean isFullscreen;
private String TAG = "VideoPlayActivity";
private String url = "";//视频url
private String title = "";//视频title
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_play);
url = getIntent().getStringExtra(KEY_VIDEO_URL);
title = getIntent().getStringExtra(KEY_VIDEO_TITLE);
mVideoLayout = findViewById(R.id.video_layout);
mVideoView = findViewById(R.id.videoView);
mMediaController = findViewById(R.id.media_controller);
ivBack = findViewById(R.id.iv_back);
mVideoView.setMediaController(mMediaController);
setVideoAreaSize();
mVideoView.setVideoURI(Uri.parse(url));
mVideoView.setVideoViewCallback(this);
mVideoView.start();
mMediaController.setTitle(title);
//返回按钮,结束Activity
ivBack.setOnClickListener(v -> VideoPlayActivity.this.finish());
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.d(TAG, "onCompletion ");
}
});
}
/**
* 置视频区域大小
*/
private void setVideoAreaSize() {
mVideoLayout.post(() -> {
int width = mVideoLayout.getWidth();
cachedHeight = (int) (width * 405f / 720f);
ViewGroup.LayoutParams videoLayoutParams = mVideoLayout.getLayoutParams();
videoLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
videoLayoutParams.height = cachedHeight;
mVideoLayout.setLayoutParams(videoLayoutParams);
mVideoView.setVideoPath(url);
mVideoView.requestFocus();
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState Position=" + mVideoView.getCurrentPosition());
outState.putInt(SEEK_POSITION_KEY, mSeekPosition);
}
@Override
protected void onRestoreInstanceState(Bundle outState) {
super.onRestoreInstanceState(outState);
mSeekPosition = outState.getInt(SEEK_POSITION_KEY);
Log.d(TAG, "onRestoreInstanceState Position=" + mSeekPosition);
}
@Override
public void onScaleChange(boolean isFullscreen) {
this.isFullscreen = isFullscreen;
if (isFullscreen) {
//横屏
ViewGroup.LayoutParams layoutParams = mVideoLayout.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
mVideoLayout.setLayoutParams(layoutParams);
ivBack.setVisibility(View.GONE);
} else {
//竖屏
ViewGroup.LayoutParams layoutParams = mVideoLayout.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = this.cachedHeight;
mVideoLayout.setLayoutParams(layoutParams);
ivBack.setVisibility(View.VISIBLE);
}
switchTitleBar(!isFullscreen);
}
@Override
public void onPause(MediaPlayer mediaPlayer) {
}
private void switchTitleBar(boolean show) {
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
if (show) {
supportActionBar.show();
} else {
supportActionBar.hide();
}
}
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause ");
if (mVideoView != null && mVideoView.isPlaying()) {
mSeekPosition = mVideoView.getCurrentPosition();
Log.d(TAG, "onPause mSeekPosition=" + mSeekPosition);
mVideoView.pause();
}
}
public static Intent newIntent(Context context, String url, String title) {
Intent intent = new Intent(context, VideoPlayActivity.class);
intent.putExtra(KEY_VIDEO_URL, url);
intent.putExtra(KEY_VIDEO_TITLE, title);
return intent;
}
@Override
public void onStart(MediaPlayer mediaPlayer) {
Log.d(TAG, "onStart UniversalVideoView callback");
}
@Override
public void onBufferingStart(MediaPlayer mediaPlayer) {
Log.d(TAG, "onBufferingStart UniversalVideoView callback");
}
@Override
public void onBufferingEnd(MediaPlayer mediaPlayer) {
Log.d(TAG, "onBufferingEnd UniversalVideoView callback");
}
@Override
public void onBackPressed() {
if (this.isFullscreen) {
mVideoView.setFullscreen(false);
} else {
super.onBackPressed();
}
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}
另外,此View并不会保存播放状态,至于播放状态和时间的保存。需要自己做相应的操作。
还有,如果横竖屏切换(半屏/全屏),Activity生命周期会重新执行,如果不需要重新执行生命周期的话,可在 AndroidManifest 对应的Activity中添加如下属性即可:
android:configChanges="orientation|keyboardHidden|screenSize"
到此,基本的播放就可以实现了。至于相关的业务订制。可在Activity中的相关回调里完成。最后再来看几个UI相关的属性
属性 | 说明 |
---|---|
uvv_fitXY | UniversalVideoView的属性,布尔值,true时设置视频缩放时在X,Y方向上铺满View设置的宽度和高度,这样可能使视频变形.false时则缩放时保持视频的长宽比例,与SDK中的VideoView类似. |
uvv_autoRotation | UniversalVideoView的属性,布尔值,true时视频会根据重力响应通知客户进行全屏与非全屏之间的切换. |
uvv_scalable | UniversalMediaController属性,布尔值,是否显示控制条右下方的缩放按钮,如果不想全屏播放时,可以设置为false不显示. |
END