文章目录
- 前言
- 一、使用手机自带播放器
- 二、VideoView(需要自定义UI控制)
- 三、TextureView(需要自定义UI)
- 四、ijkPlayer(需要自定义UI)
- 五、jiaoziVideoPlayer(有完善UI控制)
- 六、GSYVideoPlayer(有完善UI控制)
- 七、Media3(有完善UI控制)
- 八、AliPlayer
前言
本文用来记录Android中进行视频播放时的多种方案,会持续进行更新,将遇到的不同方案全部记录下来。
一、使用手机自带播放器
将视频资源通过手机自带的播放器进行操作,好处是操作简单,缺点是需要确定手机有相应的播放器,无法进行播放器的定制化,常用来播放本地资源。
kotlin
播放网络资源时:
val uri = data.mvdata.sq.backupdownurl.firstOrNull()?.toUri()
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri,"video/mp4")
}
startActivity(intent)
//可显示选择播放器
// startActivity(Intent.createChooser(intent, "选择播放器"))
播放本地资源时:
val uri = (Environment.getExternalStorageDirectory().getPath()+"video/mp4").toUri()
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri,"video/mp4")
}
startActivity(intent)
//可显示选择播放器
//startActivity(Intent.createChooser(intent, "选择播放器"))
二、VideoView(需要自定义UI控制)
系统自带的控件,可以快速简单继承,缺点是不能进行透明设置与动画设置,本身是继承自SurfaceView,内部包装了MediaPlayer的相关操作去实现视频的具体播放,因此不支持硬解码与部分高清格式的媒体。
kotlin
xml页面:
<LinearLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.VedioActivity">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
使用的主页面:
1.控件实例化
val videoView = findViewById(R.id.video_view)
2.进行控件的操作设置
//通过网络路径进入加载状态,异步
videoView.setVideoPath(data.mvdata.sq.backupdownurl.firstOrNull())
// videoView.setVideoURI() 也可以使用本地资源等
//创建媒体控制器
val mediaController= MediaController(this)
mediaController.setAnchorView(videoView) //将控制条与videoView绑定
//关联媒体控制器
videoView.setMediaController(mediaController)
videoView.setOnPreparedListener { mediaPlayer -> //使用异步监听防止加载过长导致异常
mediaPlayer .isLooping = true //设置循环播放
mediaPlayer .setVolume(1.0f,1.0f) //可设置音量
videoView.start()
val duration = mediaPlayer .duration //获取视频总时长,ms
}
3.根据当前页面的生命周期进行videoView生命周期的管理
override fun onPause() {
super.onPause()
videoView.pause()
}
override fun onResume() {
super.onResume()
videoView.start()
}
override fun onDestroy() {
super.onDestroy()
videoView.stopPlayback() //停止后重新开启需要再次将资源加载进内存
}
三、TextureView(需要自定义UI)
API 级别 14(ICS)及以上版本引入的一个视图组件,继承自View,优点时时可以对其进行透明度与动画操作,拥有更好的UI效果与灵活性,更可以添加到列表中显示,缺点是绘制效率不如SurfaceView,且必须依赖于硬件加速,即设备必须有GPU且清单文件中设置硬件加速,使用时需注意监听的设置时机并及时销毁。
由于该演示使用了MVP架构,且播放的视频需要通过网络获取播放链接,所以只有在接口回调的success方法
里面才能获取到链接,又因为textureView在创建SurfaceTexture之后就回调视图完成的方法,因此监听的设置
需要放置早一点避免该方法已经执行完才去监听,最迟也必须在OnResume里面,之前就因此放在网络接口回调中导致textureView的回调没能被及时监听,同时必须通过url跟监听中SurfaceTexture两个实例都有值时才能时期正常播放内容。
kotlin
设置硬件加速:(清单文件中可以放在Application或当前activity中)
android:hardwareAccelerated="true"
activity的xml页面:
<LinearLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.VedioActivity">
<TextureView
android:id="@+id/texture_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
activity页面:
class VedioActivity : BaseActivity(), BaseListViewInterface<MvPlayBeanGson>,
TextureView.SurfaceTextureListener {
override fun getViewId(): Int = R.layout.activity_vedio
private lateinit var textureView: TextureView
private var mediaPlayer: MediaPlayer? = null
private var url: String? = null //保存mv的网络链接
private var surfaceTexture: SurfaceTexture? = null //保存监听中获取的surfaceTexture对象
//mv播放界面的P层实现对象
private var mvPlayPresenterImpl: MvPlayPresenterImpl? = null
override fun initView() {
textureView = findViewById(R.id.texture_view)
}
override fun initData() {
//获取传递过来的hash
val hash = intent.getStringExtra("key").toString()
//发起网络请求,获取当前条目的MV资源
val mv_hash = AppConstants.URL_MV_PLAY.replace("{hash}", hash)
//实例化P层对象
mvPlayPresenterImpl = MvPlayPresenterImpl(mv_hash, this)
mvPlayPresenterImpl?.loadDatas(AppConstants.TYPE_INIT_REFRESH)
/**
* TextureView 接口注册的时机需要早一点,因为onResume()方法执行后textureView会创建SurfaceTexture再触发回调,
* 所以此监听如果放置在网络请求结果后,会导致监听注册太迟,SurfaceTexture已经创建完毕了
*/
textureView.surfaceTextureListener = this //实现该接口
}
override fun error(msg: String?) {
myToast("mv数据获取失败")
}
override fun success(type: Int, data: MvPlayBeanGson) {
myToast("mv数据获取成功")
url = data.mvdata.sq.backupdownurl.firstOrNull() //获取到url
if (surfaceTexture != null && url != null) {
initMediaPlayer(surfaceTexture!!)
}
}
override fun onDestroy() {
super.onDestroy()
//确保页面销毁时进行资源回收
releaseMediaPlayer()
}
/**
* 视图可用时,该回调会在
*/
override fun onSurfaceTextureAvailable(
surface: SurfaceTexture,
width: Int,
height: Int
) {
surfaceTexture = surface
if (url != null) {
initMediaPlayer(surface)
}
}
/**
* 视图销毁时
* 返回true则表示应用已完成资源释放,允许系统自动销毁SurfaceTexture
* 返回false则需要手动调用release()来释放资源
*/
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
Log.i("VedioActivity", "onSurfaceTextureDestroyed: ")
releaseMediaPlayer()
return true //常用
}
/**
* 视图尺寸改变时
*/
override fun onSurfaceTextureSizeChanged(
surface: SurfaceTexture,
width: Int,
height: Int
) {
Log.i("VedioActivity", "onSurfaceTextureSizeChanged: ")
}
/**
* 视图更新时
*/
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
Log.i("VedioActivity", "onSurfaceTextureUpdated: ")
}
/**
* 自定义释放资源方法
*/
private fun releaseMediaPlayer() {
mediaPlayer?.let {
if (it.isPlaying) it.stop()
it.release() // 释放解码器、缓冲区等核心资源
mediaPlayer = null
}
}
/**这里使用了网络请求来获取当前mv资源,所以之前有个bug,将TextureView 监听设置在了网络数据返回的方法中,
* 导致监听注册太晚,创建的SurfaceTexture早以设置完毕,所以一直没有触发onSurfaceTextureAvailable回调,
* 之后改为下面方法才可以,同时需要注意使用完之后资源的释放
*/
private fun initMediaPlayer(surface: SurfaceTexture) { //设置MediaPlayer的初始化加载操作
mediaPlayer = MediaPlayer().apply {
setDataSource(url) //设置数据源
setSurface(Surface(surface)) //设置输出到 TextureView 的 SurfaceTexture
prepareAsync() //进行异步加载
start()
setOnPreparedListener { //监听
it.start() //开启
// textureView.rotation = 60f//将视图旋转
}
// it.isLooping = true //循环
}
}
}
四、ijkPlayer(需要自定义UI)
ijkPlayer作为B站开源的视频框架,适合多种播放模式,但本身已有多年不维护,且没有编译好的so库,所以使用需要自己编译对应设备的so库或者使用其他人编译好的。
这里我会放上其他编译好的库文件,但是该资源没有跟进Android15的16kb页面的格式,所以15及以上的设备会有不兼容的风险,因此,自己编译时可参考该文章Ubuntu20.04编译android平台ijkplayer源码。
引入依赖步骤:首先从 github中下载项目(https://github.com/bilibili/ijkplayer):
将ijkPlayer解压后取出里面ijkplayer-java文件作为依赖引入当前项目(如D:\download\ijkplayer-master\ijkplayer-master\android\ijkplayer\ijkplayer-java)
这里因为我已经导入过了所以爆红,正常情况下可直接点finish
然后修改模块ijkplayer-java中build.gradle中相关版本号等配置与当前项目一致,可参考如下:
kotlin
apply plugin: 'com.android.library'
android {
namespace 'tv.danmaku.ijk.media.player'//空间命名别忘记加上
compileSdk 36
defaultConfig {
minSdk 24
targetSdk 36
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
apply from: new File(rootProject.projectDir, "tools/gradle-on-demand.gradle");
进行同步后在主模块中添加ijkplayer-java模块为当前的依赖(软件左上角中File->Project Structure开启该界面):
也可以直接手动在主模块app的build.gradle中添加ijkplayer-java依赖:
最后需要将ijkPlayer中的tools文件复制过来,否则会提示这里找不到tools文件
kotlin
apply from: new File(rootProject.projectDir, "tools/gradle-on-demand.gradle");
注意需要复制的是ijkPlayer项目中该路径下的tools文件(D:\download\ijkplayer-master\ijkplayer-master\android\ijkplayer\tools),存放在最外层工程目录下
最后将so文件复制到项目中,可以只针对目标机型的cpu架构,没必要全部复制进去
最后进行同步就可以使用了。
kotlin
xml页面:
<LinearLayout 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.activity.VedioActivity">
<SurfaceView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</LinearLayout>
activity页面:(这里包含了当前项目的部分逻辑,所以可根据序号标点来捋顺重点使用逻辑)
class VedioActivity : BaseActivity(), BaseListViewInterface<MvPlayBeanGson> {
override fun getViewId(): Int {
return R.layout.activity_vedio
}
//mv播放界面的P层实现对象
private var mvPlayPresenterImpl: MvPlayPresenterImpl? = null
// 状态标记(避免空指针/重复操作)
private var isPlayerInited = false // 播放器是否初始化完成
private var isSurfaceReady = false // Surface是否就绪
//播放视频的容器
private lateinit var videoView: SurfaceView
//ijkPlayer控制器
private var ijkMediaPlayer: IjkMediaPlayer? = null
override fun initView() {
videoView = findViewById(R.id.video_view)
}
override fun initData() {
//获取传递过来的hash
val hash = intent.getStringExtra("key").toString()
//发起网络请求,获取当前条目的MV资源
val mv_hash = AppConstants.URL_MV_PLAY.replace("{hash}", hash)
//实例化P层对象
mvPlayPresenterImpl = MvPlayPresenterImpl(mv_hash, this)
mvPlayPresenterImpl?.loadDatas(AppConstants.TYPE_INIT_REFRESH)
//1.监听布局完绘制的完成后给控制器绑定容器
initSurfaceView()
//2.进行ijkPlayer初始化,异步加载运行库
initIjkPlayer()
}
private fun initIjkPlayer() {
//开启子线程进行异步加载
Thread {
try {
IjkMediaPlayer.loadLibrariesOnce(null) //加载核心库
IjkMediaPlayer.native_profileBegin("libijkplayer.so")
IjkMediaPlayer.native_profileBegin("libijkffmpeg.so")
IjkMediaPlayer.native_profileBegin("libijksdl.so")
ijkMediaPlayer = IjkMediaPlayer().apply {
ThreadUtils.mainThread { //切换到主线程
setOnPreparedListener {
it.start() //异步监听加载数据完成后开始播放
}
}
}
isPlayerInited = true //标记播放器初始化完成
tryAutoPlay(null)
} catch (e: Exception) {
Log.e("VedioActivity", "IjkPlayer初始化失败", e)
finish()
}
}.start()
}
/**
* 播放
*/
private fun tryAutoPlay(url: String?) {
//3.进行播放操作
if (isPlayerInited && isSurfaceReady && url != null) {
Thread {
ijkMediaPlayer?.apply {
setDataSource(url)
prepareAsync() //异步加载资源
}
}.start()
}
}
override fun error(msg: String?) {
myToast("mv数据获取失败")
}
override fun success(type: Int, data: MvPlayBeanGson) {
myToast("mv数据获取成功")
val url = data.mvdata.sq.backupdownurl.firstOrNull() //获取到url
url?.let {
tryAutoPlay(url)
}
}
private fun initSurfaceView() {
videoView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceChanged(
holder: SurfaceHolder,
format: Int,
width: Int,
height: Int
) {
}
override fun surfaceCreated(holder: SurfaceHolder) {
isSurfaceReady = true //视图初始化完成
ThreadUtils.mainThread {
//让ijkPlayer绑定完成创建后的容器
ijkMediaPlayer?.setDisplay(holder)
}
tryAutoPlay(null)
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
if (ijkMediaPlayer?.isPlaying() == true) {
ijkMediaPlayer?.pause()
}
}
})
}
override fun onDestroy() {
super.onDestroy()
ijkMediaPlayer?.apply {
stop()
release()
}
ijkMediaPlayer = null
}
}
五、jiaoziVideoPlayer(有完善UI控制)
jiaoziVideoPlayer是一个支持高度定制的框架,里面有各种现成的ui操作,可以用最简单的方式实现视频播放。
kotlin
依赖:
implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'
xml页面:
<cn.jzvd.JzvdStd
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="200dp"
/>
activity页面:(可选择设置清单中横竖屏切换保持生命周期)
class VedioActivity : BaseActivity(), BaseListViewInterface<MvPlayBeanGson> {
override fun getViewId(): Int {
return R.layout.activity_vedio
}
//mv播放界面的P层实现对象
private var mvPlayPresenterImpl: MvPlayPresenterImpl? = null
private lateinit var videoView: JzvdStd
override fun initView() {
//1.实例化,并设置返回键逻辑
videoView = findViewById(R.id.video_view)
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// 处理返回手势的逻辑
if (Jzvd.backPress()) return
finish()
}
})
}
override fun initData() {
//获取传递过来的hash
val hash = intent.getStringExtra("key").toString()
//拼接当前条目的MV资源
val mv_hash = AppConstants.URL_MV_PLAY.replace("{hash}", hash)
//实例化P层对象后发起网络请求
mvPlayPresenterImpl = MvPlayPresenterImpl(mv_hash, this@VedioActivity)
mvPlayPresenterImpl?.loadDatas(AppConstants.TYPE_INIT_REFRESH)
}
override fun error(msg: String?) {
myToast("mv数据获取失败")
}
override fun success(type: Int, data: MvPlayBeanGson) {
myToast("mv数据获取成功")
val url = data.mvdata.sq.backupdownurl.firstOrNull() //获取到url
val title = data.songname //获取到标题
if (url == null) return
title?.let {
//2.设置数据源与标题进行播放
videoView.setUp(url,it)
}
}
override fun onPause() {
super.onPause()
//3.设置暂停与销毁的生命周期管理
Jzvd.releaseAllVideos()
}
override fun onDestroy() {
super.onDestroy()
mvPlayPresenterImpl?.destory()
mvPlayPresenterImpl = null
// 释放播放器资源
Jzvd.releaseAllVideos()
// 清空静态缓存(关键:饺子播放器需手动清空)
Jzvd.CURRENT_JZVD = null
// 释放播放器 View 引用
videoView.clearAnimation()
}
}
六、GSYVideoPlayer(有完善UI控制)
GSYVideoPlayer 是一款目前持续更新的开源库,里面集成了ExoPlayer、IjkPlayer、MediaPalyer和AliPlayer等主流媒体框架,提供了一套完整且易用的视频播放方案,同时还具有丰富的交互功能,如音量、进度条、亮度、全屏、清晰度等设置,且官网中有着比较详细的介绍可以作为参考。
网址:https://github.com/CarGuo/GSYVideoPlayer
一些定制化设置可参考该文章:GSYVideoPlayer
全面的详细demo可参考官方文档:GSYVideoPlayer 官方文档说明
kotlin
依赖:
implementation 'io.github.carguo:gsyvideoplayer:11.2.0'
xml页面:
<com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="200dp" />
activity页面:(可根据标号快速定位)
class VedioActivity : BaseActivity(), BaseListViewInterface<MvPlayBeanGson> {
override fun getViewId(): Int {
return R.layout.activity_vedio
}
//mv播放界面的P层实现对象
private var mvPlayPresenterImpl: MvPlayPresenterImpl? = null
private lateinit var videoView: StandardGSYVideoPlayer
override fun initView() {
//1.实例化,并设置返回键逻辑
videoView = findViewById(R.id.video_view)
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// 处理返回手势的逻辑
videoView.setVideoAllCallBack(null) //释放所有资源
finish()
}
})
}
override fun initData() {
//获取传递过来的hash
val hash = intent.getStringExtra("key").toString()
//拼接当前条目的MV资源
val mv_hash = AppConstants.URL_MV_PLAY.replace("{hash}", hash)
//实例化P层对象后发起网络请求
mvPlayPresenterImpl = MvPlayPresenterImpl(mv_hash, this@VedioActivity)
mvPlayPresenterImpl?.loadDatas(AppConstants.TYPE_INIT_REFRESH)
}
override fun error(msg: String?) {
myToast("mv数据获取失败")
}
override fun success(type: Int, data: MvPlayBeanGson) {
myToast("mv数据获取成功")
val url = data.mvdata.sq.backupdownurl.firstOrNull() //获取到url
val title = data.songname //获取到标题
if (url == null) return
title?.let {
/**
* 2.设置播放器的参数并进行播放
*/
//路径,是否边播边缓存,标题
videoView.setUp(url,true,title)
videoView.setIsTouchWiget(false) //是否可以在视频任意地方滑动调整进度,默认true
//设置全屏按键
videoView.fullscreenButton.setOnClickListener { //上下文,是否有actionBar,是否有状态栏(此处设置为true可以让播放器自带的标题完整显示)
videoView.startWindowFullscreen(this@VedioActivity,false,true)
}
//设置返回按键功能
videoView.backButton.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
videoView.startPlayLogic() //播放
}
}
//3.播放器的生命周期管理
override fun onPause() {
super.onPause()
videoView.onVideoPause()
}
override fun onResume() {
super.onResume()
videoView.onVideoResume()
}
override fun onDestroy() {
super.onDestroy()
//释放P层引用并解绑
mvPlayPresenterImpl?.destory()
mvPlayPresenterImpl = null
//释放播放器资源
GSYVideoManager.releaseAllVideos()
}
}
七、Media3(有完善UI控制)
Media3 是 Google 将 ExoPlayer、MediaSession、PlayerView、Cast 等多个媒体相关组件统一整合后的新架构,集成了ExoPlayer作为核心播放引擎。
更多的定制化可参考该文章:Android Media3 ExoPlayer 开发全攻略:从基础集成到高级功能实战
kotlin
依赖:
//media3流媒体框架
// 核心库
implementation "androidx.media3:media3-exoplayer:1.7.1"
// 用于 UI 组件和 MediaSession 集成
implementation "androidx.media3:media3-ui:1.7.1"
// 可选,支持DASH流媒体传输协议
implementation "androidx.media3:media3-exoplayer-dash:1.7.1"
// 可选,支持HLS流媒体传输协议
implementation "androidx.media3:media3-exoplayer-hls:1.7.1"
// 可选,支持RTSP流媒体传输协议
implementation 'androidx.media3:media3-exoplayer-rtsp:1.7.1'
/* // 用于平滑流媒体(如果不需要可以省略)
implementation "androidx.media3:media3-exoplayer-smoothstreaming:1.4.1"
// 用于使用 Transformer 进行媒体转换
implementation "androidx.media3:media3-transformer:1.4.1"
// 用于使用 Effect 进行音频/视频处理
implementation "androidx.media3:media3-effect:1.4.1"
// 用于使用 Common 和 Datasource 模块
implementation "androidx.media3:media3-common:1.4.1"
implementation "androidx.media3:media3-datasource:1.4.1"*/
xml页面:
<!--app:resize_mode 控制视频适配容器的方式
zoom等比例填充 超出部分裁剪
fit等比例显示全部画面,不足的部分黑边填充
fill强制拉伸为容器尺寸
none按原始视频显示,超出部分裁剪,不足部分黑边
fixed_width 宽度填充容器,超出部分裁剪,不足部分黑边
fixed_height 高度优先填充,超出部分裁剪,不足部分黑边-->
<androidx.media3.ui.PlayerView
android:id="@+id/video_view"
android:layout_width="match_parent"
app:resize_mode="zoom"
android:layout_height="500dp"/>
activity页面:(实现标号内容即可)
class VedioActivity : BaseActivity(), BaseListViewInterface<MvPlayBeanGson> {
override fun getViewId(): Int {
return R.layout.activity_vedio
}
//mv播放界面的P层实现对象
private var mvPlayPresenterImpl: MvPlayPresenterImpl? = null
private var player: ExoPlayer? = null
private lateinit var videoView: PlayerView
override fun initView() {
//1.实例化,并设置返回键逻辑
videoView = findViewById(R.id.video_view)
}
override fun initData() {
//获取传递过来的hash
val hash = intent.getStringExtra("key").toString()
//拼接当前条目的MV资源
val mv_hash = AppConstants.URL_MV_PLAY.replace("{hash}", hash)
//实例化P层对象后发起网络请求
mvPlayPresenterImpl = MvPlayPresenterImpl(mv_hash, this@VedioActivity)
mvPlayPresenterImpl?.loadDatas(AppConstants.TYPE_INIT_REFRESH)
}
override fun error(msg: String?) {
myToast("mv数据获取失败")
}
@OptIn(UnstableApi::class)
override fun success(type: Int, data: MvPlayBeanGson) {
myToast("mv数据获取成功")
val url = data.mvdata.sq.backupdownurl.firstOrNull() //获取到url
val title = data.songname //获取到标题
if (url == null) return
title?.let {
//2.对播放器进行初始化并进行设置
player = ExoPlayer.Builder(this@VedioActivity).build()
//将播放器附加到视图
videoView.player = player
//构建播放列表
val mediaItem = MediaItem.fromUri(url)
//设置播放列表准备播放
player?.setMediaItem(mediaItem)
player?.playWhenReady = true //当Player处于STATE_READY状态时进行播放
player?.prepare() //异步加载准备数据
player?.play()
}
}
//3.播放器的生命周期管理
override fun onPause() {
super.onPause()
player?.pause()
}
override fun onResume() {
super.onResume()
player?.play()
}
override fun onDestroy() {
super.onDestroy()
//释放P层引用并解绑
mvPlayPresenterImpl?.destory()
mvPlayPresenterImpl = null
//释放播放器资源
player?.release()
player = null
}
}
八、AliPlayer
阿里提供的播放器,支持全屏播放、视频快进/快退、播放/暂停,具备自适应码率技术,根据用户的网络状况自动调整视频质量,支持多种视频格式和流媒体协议,官网有比较详细的使用说明,且目前只支持真机调试,具体使用可根据官方文档。
官网开发文档:阿里官方集成文档






