feat:完善Exoplayer

feat:新增资源下载(Glide版本)未测试验证是否有bug
This commit is contained in:
Max
2023-11-03 15:17:50 +08:00
parent 60d60d3578
commit 4c98e9422c
6 changed files with 163 additions and 6 deletions

View File

@@ -0,0 +1,17 @@
package com.chuhai.core.download
import com.chuhai.core.exceptions.SuperException
/**
* Created by Max on 2022/5/12 21:05
* Desc:下载异常
**/
class DownloadException : SuperException {
constructor(message: String) : super(message)
constructor(throwable: Throwable) : super(
throwable
) {
}
}

View File

@@ -0,0 +1,21 @@
package com.chuhai.core.download
import java.io.File
/**
* Created by Max on 3/6/21 10:29 AM
* Desc:下载监听器
*/
interface DownloadListener {
/**
* 下载完成
*/
fun onDownloadCompleted(result: File) {}
/**
* 下载异常
*/
fun onDownloadError(exception: DownloadException) {}
}

View File

@@ -13,7 +13,7 @@ interface IPlayer : ICleared {
/**
* 绑定页面生命周期
*/
fun bindingLifeCycle(lifecycleOwner: LifecycleOwner)
fun bindLifeCycle(lifecycleOwner: LifecycleOwner)
/**
* 加载视频源加载后根据playWhenReady觉得是否播放

View File

@@ -0,0 +1,60 @@
package com.chuhai.core.player.download
import android.graphics.drawable.Drawable
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.chuhai.core.download.DownloadException
import com.chuhai.core.download.DownloadListener
import com.chuhai.utils.AppUtils
import com.chuhai.utils.log.ILog
import java.io.File
/**
* Created by Max on 2023/11/3 12:11
* Desc:Glide 实现下载器功能
* PS没有在项目中找到下载器组件之前的VAP视频是通过Glide下载的这里暂且也采用这种方式后续考虑搞个独立的下载组件
* TODO ⚠写好后还未测试验证是否有bug
**/
class GlideDownload(private val timeout: Int = 15000) : MediaDownloader, ILog {
private val targetList: ArrayList<CustomTarget<File>> by lazy {
ArrayList()
}
override fun download(url: String, listener: DownloadListener) {
val target = object : CustomTarget<File>() {
override fun onResourceReady(resource: File, transition: Transition<in File>?) {
targetList.remove(this)
listener.onDownloadCompleted(resource)
}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
targetList.remove(this)
listener.onDownloadError(DownloadException("下载失败"))
}
override fun onLoadCleared(placeholder: Drawable?) {
}
}
Glide.with(AppUtils.getApp())
.asFile()
.dontTransform()
.timeout(timeout)
.load(url).into(target)
targetList.add(target)
}
override fun onCleared() {
super.onCleared()
try {
targetList.forEach {
Glide.with(AppUtils.getApp()).clear(it)
}
} catch (e: Exception) {
e.printStackTrace()
}
targetList.clear()
}
}

View File

@@ -0,0 +1,23 @@
package com.chuhai.core.player.download
import com.chuhai.core.download.DownloadListener
import com.chuhai.utils.ICleared
/**
* Created by Max on 2023/11/3 12:45
* Desc:媒体资源下载器
*/
interface MediaDownloader : ICleared {
/**
* 下载
*/
fun download(url: String, listener: DownloadListener)
/**
* 释放
*/
override fun onCleared() {
super.onCleared()
}
}

View File

@@ -3,12 +3,15 @@ package com.chuhai.core.player.exo
import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.chuhai.core.player.IPlayer
import com.chuhai.core.player.PlayerListener
import com.chuhai.core.player.PlayerMediaItem
import com.chuhai.core.player.PlaybackState
import com.chuhai.core.player.PlayerException
import com.chuhai.core.player.PlayerListener
import com.chuhai.core.player.PlayerMediaItem
import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.PlaybackException
import com.google.android.exoplayer2.Player
@@ -20,7 +23,7 @@ import com.google.android.exoplayer2.ExoPlayer as ExoPlayerImpl
* Created by Max on 2023/11/2 14:50
* Desc:基于Exo
**/
class ExoPlayer : StyledPlayerView, IPlayer {
class ExoPlayer : StyledPlayerView, IPlayer, LifecycleEventObserver {
private var currentItem: ExoMediaItem? = null
@@ -30,6 +33,9 @@ class ExoPlayer : StyledPlayerView, IPlayer {
private var listenerAdapter: Player.Listener? = null
// 操作的记录(用于感知生命周期恢复播放或其他场景的判断)
private var playWhenReadyBackup = getPlayWhenReady()
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
@@ -37,11 +43,23 @@ class ExoPlayer : StyledPlayerView, IPlayer {
attrs,
defStyleAttr
) {
player = ExoPlayerImpl.Builder(context).build()
/**
* 缓冲策略:目前先用默认的,后续结合需求场景再调整
*/
val loadControl = DefaultLoadControl.Builder()
.setBufferDurationsMs(
DefaultLoadControl.DEFAULT_MIN_BUFFER_MS,
DefaultLoadControl.DEFAULT_MAX_BUFFER_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
).build()
player = ExoPlayerImpl.Builder(context).setLoadControl(loadControl).build()
useController = false
setPlayer(player)
}
override fun bindingLifeCycle(lifecycleOwner: LifecycleOwner) {
override fun bindLifeCycle(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycle.addObserver(this)
}
override fun prepare(item: PlayerMediaItem) {
@@ -60,6 +78,7 @@ class ExoPlayer : StyledPlayerView, IPlayer {
override fun setPlayWhenReady(playWhenReady: Boolean) {
this.player.playWhenReady = playWhenReady
this.playWhenReadyBackup = playWhenReady
}
override fun getPlayWhenReady(): Boolean {
@@ -133,4 +152,21 @@ class ExoPlayer : StyledPlayerView, IPlayer {
this.currentItem?.onCleared()
this.currentItem = null
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
// TODO 这个方法的代码 还未进行测试,目前需求貌似用不上,后续需要再验证!
when (event) {
Lifecycle.Event.ON_RESUME -> {
setPlayWhenReady(playWhenReadyBackup)
}
Lifecycle.Event.ON_PAUSE -> {
player.playWhenReady = false
}
Lifecycle.Event.ON_DESTROY -> {
onCleared()
}
}
}
}