695 lines
26 KiB
Kotlin
695 lines
26 KiB
Kotlin
package relax.offline.music.activity
|
||
|
||
import android.annotation.SuppressLint
|
||
import android.graphics.Bitmap
|
||
import android.graphics.drawable.Drawable
|
||
import android.os.Handler
|
||
import android.os.Looper
|
||
import android.os.Message
|
||
import android.view.View
|
||
import android.view.animation.AnimationUtils
|
||
import androidx.annotation.OptIn
|
||
import androidx.core.net.toUri
|
||
import androidx.media3.common.MediaItem
|
||
import androidx.media3.common.PlaybackException
|
||
import androidx.media3.common.Player
|
||
import androidx.media3.common.util.UnstableApi
|
||
import androidx.media3.exoplayer.offline.Download
|
||
import androidx.media3.exoplayer.offline.DownloadManager
|
||
import androidx.media3.exoplayer.offline.DownloadRequest
|
||
import androidx.media3.exoplayer.offline.DownloadService
|
||
import androidx.recyclerview.widget.LinearLayoutManager
|
||
import com.bumptech.glide.Glide
|
||
import com.bumptech.glide.request.target.CustomTarget
|
||
import com.bumptech.glide.request.transition.Transition
|
||
import com.gyf.immersionbar.ktx.immersionBar
|
||
import relax.offline.music.R
|
||
import relax.offline.music.adapter.PlayListAdapter
|
||
import relax.offline.music.databinding.ActivityMoPlayDetailsBinding
|
||
import relax.offline.music.innertube.Innertube
|
||
import relax.offline.music.media.MediaControllerManager
|
||
import relax.offline.music.media.SongRadio
|
||
import relax.offline.music.service.MyDownloadService
|
||
import relax.offline.music.service.ViewModelMain
|
||
import relax.offline.music.sp.AppStore
|
||
import relax.offline.music.util.DownloadUtil
|
||
import relax.offline.music.util.LogTag.LogD
|
||
import relax.offline.music.util.PlayMode
|
||
import relax.offline.music.util.asMediaItem
|
||
import relax.offline.music.util.convertMillisToMinutesAndSecondsString
|
||
import kotlinx.coroutines.Dispatchers
|
||
import kotlinx.coroutines.isActive
|
||
import kotlinx.coroutines.launch
|
||
import kotlinx.coroutines.selects.select
|
||
|
||
@OptIn(UnstableApi::class)
|
||
class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
|
||
|
||
companion object {
|
||
const val PLAY_DETAILS_VIDEO_ID = "play_details_videoId"
|
||
const val PLAY_DETAILS_PLAY_LIST_ID = "play_details_playlistId"
|
||
const val PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID = "play_details_play_list_set_video_id"
|
||
const val PLAY_DETAILS_PLAY_PARAMS = "play_details_play_params"
|
||
const val PLAY_DETAILS_NAME = "play_details_name"
|
||
const val PLAY_DETAILS_DESC = "play_details_desc"
|
||
const val PLAY_DETAILS_COME_FROM = "PLAY_DETAILS_COME_FROM"
|
||
}
|
||
|
||
private lateinit var binding: ActivityMoPlayDetailsBinding
|
||
|
||
private var currentVideoID = ""
|
||
|
||
private var comeFrom: Class<*>? = null
|
||
private var playListAdapter: PlayListAdapter? = null
|
||
private var downloadManager: DownloadManager? = null
|
||
|
||
private fun initImmersionBar() {
|
||
immersionBar {
|
||
statusBarDarkFont(false)
|
||
statusBarView(binding.view)
|
||
}
|
||
}
|
||
|
||
override suspend fun main() {
|
||
binding = ActivityMoPlayDetailsBinding.inflate(layoutInflater)
|
||
setContentView(binding.root)
|
||
initImmersionBar()
|
||
initClick()
|
||
initPlayerListener()
|
||
initPlayListAdapter()
|
||
updatePlayModeUi()
|
||
val videoId = intent.getStringExtra(PLAY_DETAILS_VIDEO_ID)
|
||
val playlistId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_ID)
|
||
val playlistSetVideoId = intent.getStringExtra(PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID)
|
||
val params = intent.getStringExtra(PLAY_DETAILS_PLAY_PARAMS)
|
||
|
||
comeFrom = intent.getSerializableExtra(PLAY_DETAILS_COME_FROM) as Class<*>?
|
||
if (comeFrom != null && comeFrom == PrimaryActivity::class.java) {
|
||
LogD(TAG, "从当前播放的悬浮layout进入")
|
||
// 处理来自 PrimaryActivity 的情况
|
||
updateCurrentMediaItemInfo()
|
||
if (meController != null && meController.currentMediaItem != null) {
|
||
updateInfoUi(meController.currentMediaItem)
|
||
}
|
||
} else {
|
||
LogD(TAG, "从点击任意歌曲进入")
|
||
// if (meController != null && meController.currentMediaItem != null && videoId == meController.currentMediaItem?.mediaId) {
|
||
// //进入的id与当前的id一样就不重新去获取播放
|
||
// updateCurrentMediaItemInfo()
|
||
// updateInfoUi(meController.currentMediaItem)
|
||
// } else {
|
||
//
|
||
// }
|
||
binding.nameTv.text = intent.getStringExtra(PLAY_DETAILS_NAME)
|
||
binding.descTv.text = intent.getStringExtra(PLAY_DETAILS_DESC)
|
||
|
||
if (videoId.isNullOrEmpty()) {
|
||
finish()
|
||
return
|
||
}
|
||
//要加载数据的话就隐藏喜欢和下载按钮
|
||
binding.likeAndDownloadLayout.visibility = View.GONE
|
||
//传入进来的ID,就是进入此界面的当前ID
|
||
currentVideoID = videoId
|
||
//根据进来界面的当前ID来获取资源。
|
||
initData(
|
||
videoId,
|
||
playlistId,
|
||
playlistSetVideoId,
|
||
params
|
||
)
|
||
}
|
||
initDownloadFlow()
|
||
onReceive()
|
||
}
|
||
|
||
private suspend fun onReceive() {
|
||
while (isActive) {
|
||
select<Unit> {
|
||
events.onReceive {
|
||
when (it) {
|
||
Event.ActivityOnResume -> {
|
||
activityOnResume()
|
||
}
|
||
|
||
else -> {}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private fun activityOnResume() {
|
||
// if (meController != null && meController.currentMediaItem != null) {
|
||
// updateInfoUi(meController.currentMediaItem)
|
||
// }
|
||
}
|
||
|
||
private fun initDownloadFlow() {
|
||
ViewModelMain.modelDownloadsFlow.observe(this) { downloads ->
|
||
if (meController != null && meController.currentMediaItem != null) {
|
||
val id = meController.currentMediaItem?.mediaId
|
||
LogD(TAG, "initDownloadFlow id ->${id}")
|
||
val currentScreenDownloads = downloads[id]
|
||
if (currentScreenDownloads != null) {
|
||
LogD(TAG, "initDownloadFlow Download id->${currentScreenDownloads?.request?.id}")
|
||
updateDownloadUI(currentScreenDownloads)
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
private fun updateDownloadUI(download: Download) {
|
||
when (download.state) {
|
||
Download.STATE_DOWNLOADING -> {
|
||
binding.downloadLoading.visibility = View.VISIBLE
|
||
binding.downloadImg.setImageResource(R.drawable.download_icon)
|
||
binding.downloadImg.visibility = View.GONE
|
||
|
||
binding.downloadBtn.isClickable = false
|
||
binding.downloadBtn.isEnabled = false
|
||
}
|
||
|
||
Download.STATE_COMPLETED -> {
|
||
binding.downloadLoading.visibility = View.GONE
|
||
binding.downloadImg.setImageResource(R.drawable.download_done_icon)
|
||
binding.downloadImg.visibility = View.VISIBLE
|
||
}
|
||
|
||
Download.STATE_FAILED -> {
|
||
binding.downloadLoading.visibility = View.GONE
|
||
binding.downloadImg.setImageResource(R.drawable.error)
|
||
binding.downloadImg.visibility = View.VISIBLE
|
||
|
||
binding.downloadBtn.isClickable = true
|
||
binding.downloadBtn.isEnabled = true
|
||
}
|
||
|
||
else -> {
|
||
binding.downloadLoading.visibility = View.GONE
|
||
binding.downloadImg.setImageResource(R.drawable.download_icon)
|
||
binding.downloadImg.visibility = View.VISIBLE
|
||
|
||
binding.downloadBtn.isClickable = true
|
||
binding.downloadBtn.isEnabled = true
|
||
}
|
||
}
|
||
}
|
||
|
||
private fun updateDownloadUi(id: String) {
|
||
if (DownloadUtil.downloadResourceExist(id)) {//已经下载,按钮不可点击
|
||
binding.downloadImg.setImageResource(R.drawable.download_done_icon)
|
||
binding.downloadBtn.isClickable = false
|
||
binding.downloadBtn.isEnabled = false
|
||
} else {
|
||
binding.downloadImg.setImageResource(R.drawable.download_icon)
|
||
binding.downloadBtn.isClickable = true
|
||
binding.downloadBtn.isEnabled = true
|
||
}
|
||
}
|
||
|
||
|
||
private fun initPlayerListener() {
|
||
meController?.addListener(playerListener)
|
||
}
|
||
|
||
private fun updateCurrentMediaItemInfo() {
|
||
if (meController != null && meController.currentMediaItem != null) {
|
||
binding.playbackErrorLayout.visibility = View.GONE
|
||
binding.loadingView.visibility = View.GONE
|
||
binding.disableClicksLayout.visibility = View.GONE
|
||
val currentString =
|
||
convertMillisToMinutesAndSecondsString(MediaControllerManager.getCurrentPosition())
|
||
binding.progressDurationTv.text = currentString
|
||
if (MediaControllerManager.getDuration() > 0) {
|
||
binding.totalDurationTv.visibility = View.VISIBLE
|
||
} else {
|
||
binding.totalDurationTv.visibility = View.GONE
|
||
}
|
||
|
||
binding.totalDurationTv.text =
|
||
convertMillisToMinutesAndSecondsString(MediaControllerManager.getDuration())
|
||
binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
|
||
binding.sbProgress.value = MediaControllerManager.getCurrentPosition().toFloat()
|
||
updateProgressState()
|
||
|
||
binding.progressBar.progress = MediaControllerManager.getBufferedPosition().toInt()
|
||
binding.progressBar.max = MediaControllerManager.getDuration().toInt()
|
||
updateProgressBufferingState()
|
||
updatePlayListDataAndAdapter()
|
||
}
|
||
}
|
||
|
||
@SuppressLint("NotifyDataSetChanged")
|
||
private fun updatePlayListDataAndAdapter() {
|
||
if (meController != null && meController.currentMediaItem != null) {
|
||
val mediaItemCount = meController.mediaItemCount
|
||
val allMediaItems: MutableList<MediaItem> = mutableListOf()
|
||
for (index in 0 until mediaItemCount) {
|
||
val mediaItemAt = meController.getMediaItemAt(index)
|
||
allMediaItems.add(mediaItemAt)
|
||
}
|
||
playList.clear()
|
||
playList.addAll(allMediaItems)
|
||
playListAdapter?.notifyDataSetChanged()
|
||
}
|
||
}
|
||
|
||
private var playList: MutableList<MediaItem> = mutableListOf()
|
||
|
||
private fun initPlayListAdapter() {
|
||
playListAdapter = PlayListAdapter(
|
||
this@MoPlayDetailsActivity,
|
||
playList
|
||
)
|
||
binding.playListRv.layoutManager =
|
||
LinearLayoutManager(
|
||
this@MoPlayDetailsActivity,
|
||
LinearLayoutManager.VERTICAL,
|
||
false
|
||
)
|
||
binding.playListRv.adapter = playListAdapter
|
||
}
|
||
|
||
@SuppressLint("NotifyDataSetChanged")
|
||
private fun initClick() {
|
||
binding.backBtn.setOnClickListener {
|
||
finish()
|
||
}
|
||
binding.tryAgainBtn.setOnClickListener {
|
||
if (meController != null) {
|
||
updateInfoUi(meController.currentMediaItem)
|
||
updateProgressState()
|
||
if (!meController.isPlaying) {
|
||
meController.prepare()
|
||
meController.play()
|
||
}
|
||
}
|
||
}
|
||
binding.playModeBtn.setOnClickListener {
|
||
if (meController != null) {
|
||
val playModeCounter = (appStore.playMusicMode + 1) % 3
|
||
appStore.playMusicMode = when (playModeCounter) {
|
||
0 -> PlayMode.LIST_LOOP.value
|
||
1 -> PlayMode.SINGLE_LOOP.value
|
||
else -> PlayMode.RANDOM.value
|
||
}
|
||
when (AppStore(this).playMusicMode) {
|
||
PlayMode.LIST_LOOP.value -> {
|
||
meController.repeatMode = Player.REPEAT_MODE_ALL
|
||
meController.shuffleModeEnabled = false
|
||
}
|
||
|
||
PlayMode.SINGLE_LOOP.value -> {
|
||
meController.repeatMode = Player.REPEAT_MODE_ONE
|
||
meController.shuffleModeEnabled = false
|
||
}
|
||
|
||
PlayMode.RANDOM.value -> {
|
||
meController.repeatMode = Player.REPEAT_MODE_ALL
|
||
meController.shuffleModeEnabled = true
|
||
}
|
||
}
|
||
updatePlayModeUi()
|
||
LogD(TAG, "repeatMode->${meController.repeatMode}")
|
||
LogD(TAG, "shuffleModeEnabled->${meController.shuffleModeEnabled}")
|
||
}
|
||
}
|
||
binding.playLayoutBtn.setOnClickListener {
|
||
if (meController != null) {
|
||
if (meController.isPlaying) {
|
||
meController.pause()
|
||
updatePlayState(false)
|
||
} else {
|
||
meController.play()
|
||
updatePlayState(true)
|
||
}
|
||
updateProgressState()
|
||
}
|
||
}
|
||
binding.playSkipBackBtn.setOnClickListener {
|
||
if (meController != null) {
|
||
meController.seekToPreviousMediaItem()
|
||
updateProgressUi()
|
||
updateInfoUi(meController.currentMediaItem)
|
||
updateProgressState()
|
||
if (!meController.isPlaying) {
|
||
meController.prepare()
|
||
meController.play()
|
||
}
|
||
}
|
||
}
|
||
binding.playSkipForwardBtn.setOnClickListener {
|
||
if (meController != null) {
|
||
meController.seekToNextMediaItem()
|
||
updateProgressUi()
|
||
updateInfoUi(meController.currentMediaItem)
|
||
updateProgressState()
|
||
if (!meController.isPlaying) {
|
||
meController.prepare()
|
||
meController.play()
|
||
}
|
||
}
|
||
}
|
||
binding.listLayoutBtn.setOnClickListener {
|
||
toggleBottomLayout()
|
||
}
|
||
binding.bottomCloseBtn.setOnClickListener {
|
||
toggleBottomLayout()
|
||
}
|
||
binding.bottomBlankLayout.setOnClickListener {
|
||
toggleBottomLayout()
|
||
}
|
||
binding.progressBar.progress = 0
|
||
binding.sbProgress.value = 0f
|
||
binding.sbProgress.addOnChangeListener { slider, value, fromUser ->
|
||
if (fromUser) {
|
||
if (meController != null) {
|
||
meController.seekTo(value.toLong())
|
||
val ss = meController.isPlaying
|
||
if (!ss) {
|
||
meController.play()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
binding.downloadBtn.setOnClickListener {
|
||
if (meController != null && meController.currentMediaItem != null) {
|
||
val currentMediaItem = meController.currentMediaItem
|
||
val contentId = currentMediaItem?.mediaId ?: ""
|
||
//如果已经存在就不进行下载
|
||
if (DownloadUtil.downloadResourceExist(contentId)) {
|
||
return@setOnClickListener
|
||
}
|
||
val downloadRequest = DownloadRequest
|
||
.Builder(contentId, contentId.toUri())
|
||
.setCustomCacheKey(contentId)
|
||
.build()
|
||
DownloadService.sendAddDownload(
|
||
this,
|
||
MyDownloadService::class.java,
|
||
downloadRequest,
|
||
false
|
||
)
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
private fun updatePlayModeUi() {
|
||
binding.modePlayImg.setImageResource(
|
||
when (AppStore(this).playMusicMode) {
|
||
PlayMode.LIST_LOOP.value -> {
|
||
R.drawable.mode_cycle_play_icon
|
||
}
|
||
|
||
PlayMode.SINGLE_LOOP.value -> {
|
||
R.drawable.mode_single_play_icon
|
||
}
|
||
|
||
PlayMode.RANDOM.value -> {
|
||
R.drawable.mode_random_play_icon
|
||
}
|
||
|
||
else -> {
|
||
R.drawable.mode_cycle_play_icon
|
||
}
|
||
}
|
||
|
||
)
|
||
}
|
||
|
||
@SuppressLint("NotifyDataSetChanged")
|
||
private fun initData(
|
||
videoId: String,
|
||
playlistId: String? = null,
|
||
playlistSetVideoId: String? = null,
|
||
parameters: String? = null
|
||
) {
|
||
SongRadio(
|
||
videoId,
|
||
playlistId,
|
||
playlistSetVideoId,
|
||
parameters
|
||
).let {
|
||
launch(Dispatchers.Main) {
|
||
val songRadioList = it.process()//获取到的资源集合
|
||
|
||
if (songRadioList.isEmpty()) {//集合为空则展示错误提示
|
||
binding.loadingView.visibility = View.GONE
|
||
binding.disableClicksLayout.visibility = View.GONE
|
||
binding.playbackErrorLayout.visibility = View.VISIBLE
|
||
}
|
||
|
||
if (isFinishing) {
|
||
return@launch
|
||
}
|
||
|
||
var mediaItem: MediaItem? = null
|
||
for (song: Innertube.SongItem in songRadioList) {
|
||
if (song.key == currentVideoID) {//判断当前ID得到一个mediaItem
|
||
mediaItem = song.asMediaItem
|
||
break
|
||
}
|
||
}
|
||
|
||
if (mediaItem != null) {
|
||
//数据请求完毕mediaItem不等于空就显示喜欢与下载按钮
|
||
binding.likeAndDownloadLayout.visibility = View.VISIBLE
|
||
updateInfoUi(mediaItem)
|
||
|
||
binding.playbackErrorLayout.visibility = View.GONE
|
||
|
||
binding.totalDurationTv.visibility = View.GONE
|
||
|
||
|
||
val newMediaItem =
|
||
MediaItem.Builder()
|
||
.setMediaId(videoId)
|
||
.setUri(videoId)
|
||
.setCustomCacheKey(videoId)
|
||
.setMediaMetadata(
|
||
mediaItem.mediaMetadata
|
||
)
|
||
.build()
|
||
|
||
meController?.let {
|
||
it.setMediaItem(newMediaItem, true)
|
||
it.prepare()
|
||
it.play()
|
||
|
||
//过滤掉进入页面的id得到集合addMediaItems
|
||
val mediaItems = songRadioList.map(Innertube.SongItem::asMediaItem)
|
||
.filter { filter -> filter.mediaId != videoId }
|
||
it.addMediaItems(mediaItems)
|
||
}
|
||
|
||
updatePlayListDataAndAdapter()
|
||
} else {
|
||
binding.playbackErrorLayout.visibility = View.VISIBLE
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private val playerListener = object : Player.Listener {
|
||
@SuppressLint("NotifyDataSetChanged")
|
||
override fun onPositionDiscontinuity(
|
||
oldPosition: Player.PositionInfo,
|
||
newPosition: Player.PositionInfo,
|
||
reason: Int
|
||
) {
|
||
//保证自动播放完毕当前歌曲与通知切换歌曲可以更新UI信息
|
||
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
|
||
|| reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT
|
||
) {
|
||
updateProgressUi()
|
||
updateInfoUi(meController?.currentMediaItem)
|
||
if (playListAdapter != null) {
|
||
playListAdapter?.notifyDataSetChanged()
|
||
}
|
||
}
|
||
}
|
||
|
||
override fun onPlayerError(error: PlaybackException) {
|
||
LogD(TAG, "onPlayerError error= $error")
|
||
binding.playbackErrorLayout.visibility = View.VISIBLE//展示错误提示
|
||
|
||
updatePlayState(false)
|
||
}
|
||
|
||
override fun onPlayWhenReadyChanged(
|
||
playWhenReady: Boolean,
|
||
reason: Int
|
||
) {
|
||
updatePlayState(playWhenReady)
|
||
updateProgressState()
|
||
}
|
||
|
||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||
when (playbackState) {
|
||
Player.STATE_BUFFERING -> {
|
||
binding.loadingView.visibility = View.VISIBLE
|
||
binding.disableClicksLayout.visibility = View.VISIBLE
|
||
binding.playbackErrorLayout.visibility = View.GONE
|
||
}
|
||
|
||
Player.STATE_READY -> {
|
||
binding.playbackErrorLayout.visibility = View.GONE
|
||
binding.loadingView.visibility = View.GONE
|
||
binding.disableClicksLayout.visibility = View.GONE
|
||
binding.totalDurationTv.visibility = View.VISIBLE
|
||
binding.totalDurationTv.text =
|
||
convertMillisToMinutesAndSecondsString(
|
||
MediaControllerManager.getDuration()
|
||
)
|
||
binding.sbProgress.valueTo =
|
||
MediaControllerManager.getDuration().toFloat()
|
||
binding.progressBar.max =
|
||
MediaControllerManager.getDuration().toInt()
|
||
updateProgressBufferingState()
|
||
}
|
||
|
||
else -> {
|
||
binding.loadingView.visibility = View.GONE
|
||
binding.disableClicksLayout.visibility = View.GONE
|
||
}
|
||
}
|
||
updateProgressState()
|
||
}
|
||
}
|
||
|
||
override fun onDestroy() {
|
||
super.onDestroy()
|
||
meController?.removeListener(playerListener)
|
||
}
|
||
|
||
private fun updateProgressUi() {
|
||
binding.sbProgress.value = 0f
|
||
binding.progressBar.progress = 0
|
||
binding.progressDurationTv.text = convertMillisToMinutesAndSecondsString(0L)
|
||
binding.totalDurationTv.visibility = View.GONE
|
||
}
|
||
|
||
private fun updateInfoUi(mediaItem: MediaItem?) {
|
||
if (mediaItem == null) {
|
||
binding.playbackErrorLayout.visibility = View.VISIBLE
|
||
return
|
||
}
|
||
// currentVideoID = mediaItem.mediaId
|
||
updateDownloadUi(mediaItem.mediaId)
|
||
|
||
Glide.with(this)
|
||
.asBitmap()
|
||
.load(mediaItem.mediaMetadata.artworkUri)
|
||
.placeholder(R.mipmap.app_logo)
|
||
.into(object : CustomTarget<Bitmap>() {
|
||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||
binding.thumbnail.setImageBitmap(resource)
|
||
val blurredBitmap = applyGaussianBlur(resource, 25f, this@MoPlayDetailsActivity)
|
||
binding.imageView.setImageBitmap(blurredBitmap)
|
||
}
|
||
|
||
override fun onLoadCleared(placeholder: Drawable?) {
|
||
if (placeholder != null) {
|
||
binding.thumbnail.setImageDrawable(placeholder)
|
||
}
|
||
}
|
||
})
|
||
|
||
binding.nameTv.text = mediaItem.mediaMetadata.title
|
||
binding.descTv.text = mediaItem.mediaMetadata.artist
|
||
}
|
||
|
||
/**
|
||
* 更新播放进度
|
||
*/
|
||
private fun updateProgressState() {
|
||
//判断是否ready与播放中,否则停止更新进度
|
||
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
|
||
updatePlayState(meController.isPlaying)
|
||
progressHandler.removeCallbacksAndMessages(null)
|
||
progressHandler.sendEmptyMessage(1)
|
||
} else {
|
||
progressHandler.removeCallbacksAndMessages(null)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 播放进度
|
||
*/
|
||
private val progressHandler = object : Handler(Looper.myLooper()!!) {
|
||
override fun handleMessage(msg: Message) {
|
||
//判断是否ready与播放中,否则停止更新进度
|
||
if (meController != null && meController.playbackState == Player.STATE_READY && meController.isPlaying) {
|
||
val currentPosition = MediaControllerManager.getCurrentPosition()
|
||
val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
|
||
binding.progressDurationTv.text = currentString
|
||
|
||
val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
|
||
binding.progressBar.progress = currentBufferedPosition.toInt()
|
||
|
||
// 更新 SeekBar 的进度
|
||
binding.sbProgress.value = currentPosition.toFloat()
|
||
|
||
sendEmptyMessageDelayed(1, 50)
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新缓冲进度
|
||
*/
|
||
private fun updateProgressBufferingState() {
|
||
if (meController != null && meController.isLoading) {
|
||
progressBufferingHandler.removeCallbacksAndMessages(null)
|
||
progressBufferingHandler.sendEmptyMessage(1)
|
||
} else {
|
||
progressBufferingHandler.removeCallbacksAndMessages(null)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 缓冲进度
|
||
*/
|
||
private val progressBufferingHandler = object : Handler(Looper.myLooper()!!) {
|
||
override fun handleMessage(msg: Message) {
|
||
if (meController != null && meController.isLoading) {
|
||
val currentBufferedPosition = MediaControllerManager.getBufferedPosition()
|
||
binding.progressBar.progress = currentBufferedPosition.toInt()
|
||
sendEmptyMessageDelayed(1, 50)
|
||
}
|
||
}
|
||
}
|
||
|
||
private fun updatePlayState(b: Boolean) {
|
||
if (b) {
|
||
binding.playImg.setImageResource(R.drawable.playing_green_icon)
|
||
} else {
|
||
binding.playImg.setImageResource(R.drawable.play_green_icon)
|
||
}
|
||
}
|
||
|
||
|
||
private fun toggleBottomLayout() {
|
||
if (binding.bottomLayout.visibility == View.VISIBLE) {
|
||
hideBottomLayout()
|
||
} else {
|
||
showBottomLayout()
|
||
}
|
||
}
|
||
|
||
private fun showBottomLayout() {
|
||
val slideUpAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up)
|
||
binding.bottomLayout.startAnimation(slideUpAnimation)
|
||
binding.bottomLayout.visibility = View.VISIBLE
|
||
}
|
||
|
||
private fun hideBottomLayout() {
|
||
val slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down)
|
||
binding.bottomLayout.startAnimation(slideDownAnimation)
|
||
binding.bottomLayout.visibility = View.GONE
|
||
}
|
||
} |