需求: 实现视频列表的自动播放,无需用户操作。
在使用Texture遇到一个问题。在RK3288 盒子上,直接AndroidStudio 运行app 播放正常,退出到桌面再次打开还是正常播放。。但是当我打包之后,安装apk运行,重复之前的操作就会频繁出现有声音没有画面的bug。。。
猜想: 就是姿势不对呗,反正就是一顿瞎捣鼓。
kotlin 代码如下,有些无用代码就懒得删除了。
播放帮助类
class MyPlayerHelper {
companion object {
const val TAG = "MyPlayerHelper"
val shared: MyPlayerHelper by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
MyPlayerHelper()
}
}
enum class PlayStatus {
stop,
playing,
paused
}
private var mediaPlayer: MediaPlayer? = null
private var curStatus: PlayStatus = PlayStatus.stop
private var ltVideoWrapper: LinearLayout? = null
private var lastPosition: Int = 0
private var mSurface: Surface? = null
private var videoList: ArrayList<Video> = ArrayList()
private var videoIdx = 0
private fun videoListChanged(list: List<Video>) : Boolean {
if (list.size != videoList.size) return true
if (videoList.containsAll(list) && list.containsAll(videoList)) {
return false
}
return true
}
/**
* 初始化 播放器
*/
private fun initPlayer() {
AppHelper.logD(TAG, "lxf video initPlayer")
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer()
mediaPlayer!!.setScreenOnWhilePlaying(true)
mediaPlayer!!.setOnCompletionListener(object : MediaPlayer.OnCompletionListener {
override fun onCompletion(mp: MediaPlayer?) {
//播放完成
if (videoList.size > 1) {
playNext()
} else {
mp?.isLooping = true
}
}
})
mediaPlayer?.setOnErrorListener(object : MediaPlayer.OnErrorListener {
override fun onError(mp: MediaPlayer?, p1: Int, p2: Int): Boolean {
return false
}
})
mediaPlayer?.setOnInfoListener(object : MediaPlayer.OnInfoListener {
override fun onInfo(mp: MediaPlayer?, p1: Int, p2: Int): Boolean {
return false
}
})
mediaPlayer?.setOnPreparedListener(object : MediaPlayer.OnPreparedListener {
override fun onPrepared(mp: MediaPlayer?) {
// mp?.seekTo(lastPosition)
mp?.start()
}
})
mediaPlayer?.setOnSeekCompleteListener(object : MediaPlayer.OnSeekCompleteListener {
override fun onSeekComplete(mp: MediaPlayer?) {
// AppHelper.logD(TAG, "lxf video onSeekComplete")
// mp?.start()
}
})
mediaPlayer?.setOnVideoSizeChangedListener(object :
MediaPlayer.OnVideoSizeChangedListener {
override fun onVideoSizeChanged(mp: MediaPlayer?, p1: Int, p2: Int) {
// videoFitCenter()
}
})
}
}
/**
* 播放下一个
*/
private fun playNext() {
AppHelper.logD(TAG, "lxf video playNext")
videoIdx += 1
play()
}
/**
* 播放
*/
private fun play() {
AppHelper.logD(TAG, "lxf video play")
try {
if (videoList.size == 0){
return
}
if (videoIdx >= videoList.size) {
videoIdx = 0
lastPosition = 0
}
initPlayer()
val content = videoList[videoIdx]
//网络播放
val url: String = content.videoUrl
val fileName = content.getVideoName()
val filePath = AppHelper.shared.getFileDownloadPath() + fileName
val file = File(filePath)
mediaPlayer?.let {
it.reset()
it.setSurface(mSurface)
if (file.exists()) {
it.setDataSource(filePath)
} else {
it.setDataSource(url)
}
it.prepareAsync()
}
} catch (e: Exception) {
e.printStackTrace()
AppHelper.logD(TAG, "lxf video play Exception")
val txt: String = Date().format("yyyy-MM-dd HH:mm:ss \n") + LzApplication.shared().tek.ethMac + AppHelper.shared.currentWharf?.name + "视频播放异常\n${e.localizedMessage}"
AppHelper.shared.uploadCrashLog(txt)
}
}
/**
* 更新画面
*/
fun updateSurfaceTexture(surface: SurfaceTexture) {
mSurface = Surface(surface)
// mediaPlayer?.setSurface(mSurface)
}
/**
* 开始播放视频
*/
fun startPlay(surface: SurfaceTexture) {
mSurface = Surface(surface)
play()
}
/**
* 停止播放
*/
fun isStop() : Boolean {
return curStatus == PlayStatus.stop
}
/**
* 暂停播放
*/
fun isPaused() : Boolean {
return curStatus == PlayStatus.paused
}
/**
* 正在播放
*/
fun isPlaying() : Boolean {
return curStatus == PlayStatus.playing
}
/**
* 开始播放
*/
fun setPlayList(list: List<Video>) {
if (videoListChanged(list)) {
AppHelper.logD(TAG, "lxf video setPlayList")
videoList.clear()
videoList.addAll(list)
//
// ///
// if (curStatus == PlayStatus.stop) {
// videoIdx = 0
// play()
// }
}
}
/**
* 停止播放
*/
fun stopPlay() {
AppHelper.logD(TAG, "lxf video stopPlay")
mSurface = null
mediaPlayer?.stop()
mediaPlayer?.release()
mediaPlayer = null
curStatus = PlayStatus.stop
videoIdx = 0
videoList.clear()
}
/**
* 继续播放
*/
fun continuePlay() {
AppHelper.logD(TAG, " continuePlay")
if (curStatus == PlayStatus.paused) {
mediaPlayer?.let {
if (!it.isPlaying) {
it.start()
curStatus = PlayStatus.playing
AppHelper.logD(TAG, " continuePlay 继续播放")
}
}
} else if (curStatus == PlayStatus.stop) {
AppHelper.logD(TAG, " continuePlay 从头播放")
videoIdx = 0
play()
}
}
/**
* 暂停播放
*/
fun pausePlay() {
AppHelper.logD(TAG, "lxf video pausePlay")
mediaPlayer?.let {
if (it.isPlaying && curStatus != PlayStatus.paused) {
it.pause()
lastPosition = it.currentPosition
curStatus = PlayStatus.paused
}
}
}
/**
* 将视频居中对齐
*/
private fun videoFitCenter() {
ltVideoWrapper?.let {
var vWidth: Int = mediaPlayer?.videoWidth ?: 0
var vHeight: Int = mediaPlayer?.videoHeight ?: 0
val lw: Int = it.width
val lh: Int = it.height
if (vWidth > lw || vHeight > lh) {
val rw = vWidth * 1f / lw
val rh = vHeight * 1f / lh
val r = max(rw, rh)
vWidth = ceil(vWidth * 1f / r).toInt()
vHeight = ceil(vHeight * 1f / r).toInt()
}
val lp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(vWidth, vHeight)
lp.gravity = Gravity.CENTER
// surfaceView?.layoutParams = lp
}
}
}
/***
* 增加监听
*/
private fun addSurfaceTextureListener() {
textureView?.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(
surface: SurfaceTexture,
width: Int,
height: Int
) {
AppHelper.logD(MyPlayerHelper.TAG, "onSurfaceTextureAvailable")
MyPlayerHelper.shared.startPlay(surface)
}
override fun onSurfaceTextureSizeChanged(
surface: SurfaceTexture,
width: Int,
height: Int
) {
AppHelper.logD(MyPlayerHelper.TAG, "onSurfaceTextureSizeChanged")
}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
AppHelper.logD(MyPlayerHelper.TAG, "onSurfaceTextureDestroyed")
MyPlayerHelper.shared.stopPlay()
return true
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
// MyPlayerHelper.shared.updateSurfaceTexture(surface)
}
}
}
网友评论