相关文章
【重生之我在学Android原生】ContentProvider(Java)
【重生之我在学Android原生】Media3
前言
内容颇多,尽量从简
ExoPlayer使用
实现效果
Android(java)
使用ExoPlayer播放视频,自定义ExoPlayer界面,记录播放位置(横屏竖屏切换/切换至后台等)
案例实现
创建项目
添加依赖
Sync 一下
/// Jetpack Media3 ExoPlayer
implementation ("androidx.media3:media3-exoplayer:1.3.1")
implementation ("androidx.media3:media3-ui:1.3.1")
implementation ("androidx.media3:media3-common:1.3.1")
转到activity_main.xml
选择Player.View
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.media3.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
player初始化
要在Activity的生命周期中完成player的初始化销毁等
package com.test.exoplayerexampleapplication;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.ui.PlayerView;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@OptIn(markerClass = UnstableApi.class) @Override
protected void onStart() {
super.onStart();
if (Util.SDK_INT >= 24) {
initializePlayer();
}
}
@OptIn(markerClass = UnstableApi.class) @Override
protected void onResume() {
super.onResume();
if (Util.SDK_INT < 24) {
initializePlayer();
}
}
private void initializePlayer() {
}
}
定义PlayerView,ExoPlayer
private PlayerView playerView;
private ExoPlayer exoPlayer;
private final Uri videoOneUri = Uri.parse("http://www.w3school.com.cn/example/html5/mov_bbb.mp4");
在AndroidManifest.xml中定义网络权限,如果链接是Http,还需加userCleartextTraffic
<uses-permission android:name="android.permission.INTERNET" />
android:usesCleartextTraffic="true"
定义initializePlayer()方法
private void initializePlayer() {
playerView = findViewById(R.id.video_view);
exoPlayer = new ExoPlayer.Builder(this).build();
playerView.setPlayer(exoPlayer);
MediaItem mediaItem = MediaItem.fromUri(videoOneUri);
exoPlayer.addMediaItem(mediaItem);
exoPlayer.prepare();
}
运行可以播放视频
释放资源
媒体播放器是很占用资源的,所以当不再需要播放器时,要释放它,当然也要在Activity的生命周期中释放资源
在onStop和onPause适当调用
@OptIn(markerClass = UnstableApi.class) @Override
protected void onPause() {
super.onPause();
if (Util.SDK_INT < 24) {
releasePlayer();
}
}
@OptIn(markerClass = UnstableApi.class) @Override
protected void onStop() {
super.onStop();
if (Util.SDK_INT >= 24) {
releasePlayer();
}
}
private void releasePlayer() {
exoPlayer.release();
}
记录视频的播放状态
重新运行项目,测试切换至后台
切换至后台的生命周期,可以知道当APP放到后台,会调用player.release()方法释放
我们发现视频切换到后台,再切换回来,之前的播放到第四秒,切换回来发现,又回到第0秒。所以,现在需要记录之前播放的位置,播放的状态,播放到第几个视频了。
既然没有onDestory掉Activity
那么定义三个变量(播放位置,播放状态,第几个视频)
private Long playbackPosition = 0L;
private int currentMediaItemIndex = 0;
private boolean playWhenReady = false;
playbackPosition = exoPlayer.getCurrentPosition();
currentMediaItemIndex = exoPlayer.getCurrentMediaItemIndex();
playWhenReady = exoPlayer.getPlayWhenReady();
exoPlayer.setPlayWhenReady(playWhenReady);
exoPlayer.seekTo(currentMediaItemIndex, playbackPosition);
添加新的视频链接
private final Uri videoTwoUri = Uri.parse("https://media.w3.org/2010/05/sintel/trailer.mp4");
运行测试,播放下一个视频,并播放至一半,切换到后台,再切换回来
横竖屏切换
横竖屏切换的生命周期,Activity被Destory了
使用SharedPreference来存储键值对,参考官方文档,官方推荐用DataStore
那使用DataStore
我们现在做的事情是,使用DataStore Preference来存储视频在释放之前的播放进度,播放状态,播放到第几个视频了。
按照官网配置Preferences DataStore
引入依赖
/// Preferences DataStore
implementation("androidx.datastore:datastore-preferences:1.0.0")
/// RxJava2 support
implementation("androidx.datastore:datastore-preferences-rxjava2:1.0.0")
/// RxJava3 support
implementation("androidx.datastore:datastore-preferences-rxjava3:1.0.0")
实例RxDataStore,销毁
private RxDataStore<Preferences> dataStore;
if (dataStore == null) {
dataStore = new RxPreferenceDataStoreBuilder(this, "ExoPlayerKeys").build();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (dataStore != null) {
dataStore.dispose();
}
}
定义三个Key
Preferences.Key<Integer> currentMediaItemIndexPK;
Preferences.Key<Integer> playbackPositionPK;
Preferences.Key<Boolean> playWhenReadyPK;
currentMediaItemIndexPK = PreferencesKeys.intKey("currentMediaItemIndex");
playbackPositionPK = PreferencesKeys.intKey("playbackPosition");
playWhenReadyPK = PreferencesKeys.booleanKey("playWhenReady");
使用PreferencesKeys存储值
private void saveVideoRecord() {
dataStore.updateDataAsync(preferences -> {
MutablePreferences mutablePreferences = preferences.toMutablePreferences();
mutablePreferences.set(currentMediaItemIndexPK, currentMediaItemIndex);
mutablePreferences.set(playbackPositionPK, playbackPosition.intValue());
mutablePreferences.set(playWhenReadyPK, playWhenReady);
return Single.