添加下载提示。

This commit is contained in:
ocean 2024-06-20 18:21:23 +08:00
parent c7e66e2ab2
commit b159bb178a
6 changed files with 141 additions and 119 deletions

View File

@ -92,19 +92,19 @@ class LaunchActivity : MoBaseActivity() {
} }
private fun toMainActivity() { private fun toMainActivity() {
if (!withPermission()) { // if (!withPermission()) {
if (type == 1) {//如果type等于1则是从后台进入的应用不进行跳转直接关闭启动页 // if (type == 1) {//如果type等于1则是从后台进入的应用不进行跳转直接关闭启动页
finish() // finish()
return // return
} // }
startActivity(Intent(this, MainActivity::class.java)) // startActivity(Intent(this, MainActivity::class.java))
} else { // } else {
if (type == 1) { if (type == 1) {
finish() finish()
return return
} }
startActivity(Intent(this, PrimaryActivity::class.java)) startActivity(Intent(this, PrimaryActivity::class.java))
} // }
} }
private fun loadAd() { private fun loadAd() {

View File

@ -1,18 +1,19 @@
package melody.offline.music.activity package melody.offline.music.activity
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.view.View import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.adapter.DetailsListAdapter import melody.offline.music.adapter.DetailsListAdapter
import melody.offline.music.databinding.ActivityDetailsBinding import melody.offline.music.databinding.ActivityDetailsBinding
import melody.offline.music.innertube.Innertube import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.requests.moPlaylistPage import melody.offline.music.innertube.requests.moPlaylistPage
import melody.offline.music.util.LogTag.LogD import melody.offline.music.util.LogTag.LogD
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
class MoListDetailsActivity : MoBaseActivity() { class MoListDetailsActivity : MoBaseActivity() {
private val requests: Channel<Request> = Channel(Channel.UNLIMITED) private val requests: Channel<Request> = Channel(Channel.UNLIMITED)
@ -29,6 +30,9 @@ class MoListDetailsActivity : MoBaseActivity() {
private var browseId: String? = null private var browseId: String? = null
private var adapter: DetailsListAdapter? = null private var adapter: DetailsListAdapter? = null
private var myList: MutableList<Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean> =
mutableListOf()
override suspend fun main() { override suspend fun main() {
binding = ActivityDetailsBinding.inflate(layoutInflater) binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -97,34 +101,51 @@ class MoListDetailsActivity : MoBaseActivity() {
binding.tryAgainBtn.setOnClickListener { binding.tryAgainBtn.setOnClickListener {
requests.trySend(Request.TryAgain) requests.trySend(Request.TryAgain)
} }
binding.playAllBtn.setOnClickListener {
if (myList.isNotEmpty()) {
val bean = myList[0]
val intent = Intent(this, MoPlayDetailsActivity::class.java)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_VIDEO_ID, bean.videoId)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_ID, bean.playlistId)
intent.putExtra(
MoPlayDetailsActivity.PLAY_DETAILS_PLAY_LIST_SET_VIDEO_ID,
bean.playlistSetVideoId
)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_PLAY_PARAMS, bean.params)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_NAME, bean.title)
intent.putExtra(MoPlayDetailsActivity.PLAY_DETAILS_DESC, bean.name)
startActivity(intent)
}
}
} }
private suspend fun initData(browseId: String) { private suspend fun initData(browseId: String) {
showLoadingUi() showLoadingUi()
Innertube.moPlaylistPage(browseId) Innertube.moPlaylistPage(browseId)?.onSuccess {
?.onSuccess { if (this.isDestroyed || this.isFinishing) {
if (this.isDestroyed || this.isFinishing) { return
return
}
showDataUi()
Glide.with(this)
.load(it.thumbnail)
.into(binding.imageView)
binding.title.text = it.title
binding.subtitle.text = it.subtitle
binding.secondSubtitle.text = it.secondSubtitle
adapter = DetailsListAdapter(this, it.moPlaylistOrAlbumListBean)
binding.rv.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter
}?.onFailure {
showNoContentUi()
LogD(TAG, "moPlaylistPage onFailure->${it}")
} }
showDataUi()
Glide.with(this).load(it.thumbnail).into(binding.imageView)
binding.title.text = it.title
binding.subtitle.text = it.subtitle
binding.secondSubtitle.text = it.secondSubtitle
adapter = DetailsListAdapter(this, it.moPlaylistOrAlbumListBean)
binding.rv.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
binding.rv.adapter = adapter
myList.clear()
myList.addAll(it.moPlaylistOrAlbumListBean)
}?.onFailure {
showNoContentUi()
LogD(TAG, "moPlaylistPage onFailure->${it}")
}
} }
private fun showDataUi() { private fun showDataUi() {

View File

@ -8,6 +8,7 @@ import android.os.Looper
import android.os.Message import android.os.Message
import android.view.View import android.view.View
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.widget.Toast
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
@ -115,8 +116,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
//从数据库获取所有的offline //从数据库获取所有的offline
val offlineBeans = App.appOfflineDBManager.getAllOfflineBeans() val offlineBeans = App.appOfflineDBManager.getAllOfflineBeans()
//过滤只有大小大于0的才添加到集合中 //过滤只有大小大于0的才添加到集合中
val allFilteredBeans = offlineBeans val allFilteredBeans =
.filter { it.bytesDownloaded?.let { bytes -> bytes > 0 } == true } offlineBeans.filter { it.bytesDownloaded?.let { bytes -> bytes > 0 } == true }
//找到当前点击进来的歌曲media //找到当前点击进来的歌曲media
val findCurrentMedia = allFilteredBeans.find { it.videoId == videoId }?.asMediaItem val findCurrentMedia = allFilteredBeans.find { it.videoId == videoId }?.asMediaItem
if (findCurrentMedia != null) { if (findCurrentMedia != null) {
@ -128,9 +129,9 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
it.setMediaItem(findCurrentMedia, true) it.setMediaItem(findCurrentMedia, true)
it.prepare() it.prepare()
it.play() it.play()
val mediaItems = allFilteredBeans val mediaItems =
.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem allFilteredBeans.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem
.filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。 .filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。
it.addMediaItems(mediaItems) it.addMediaItems(mediaItems)
} }
updatePlayListDataAndAdapter() updatePlayListDataAndAdapter()
@ -154,9 +155,9 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
it.setMediaItem(findCurrentMedia, true) it.setMediaItem(findCurrentMedia, true)
it.prepare() it.prepare()
it.play() it.play()
val mediaItems = allFilteredBeans val mediaItems =
.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem allFilteredBeans.map { mapAll -> mapAll.asMediaItem }//转换成MediaItem
.filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。 .filter { filter -> filter.mediaId != videoId }//过滤掉id相等的。
it.addMediaItems(mediaItems) it.addMediaItems(mediaItems)
} }
updatePlayListDataAndAdapter() updatePlayListDataAndAdapter()
@ -178,10 +179,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
currentVideoID = videoId currentVideoID = videoId
//根据进来界面的当前ID来获取资源。 //根据进来界面的当前ID来获取资源。
initData( initData(
videoId, videoId, playlistId, playlistSetVideoId, params
playlistId,
playlistSetVideoId,
params
) )
} }
loadAd() loadAd()
@ -208,13 +206,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
val currentMediaItem = meController.currentMediaItem val currentMediaItem = meController.currentMediaItem
val jsonObject = JSONObject() val jsonObject = JSONObject()
jsonObject.put( jsonObject.put(
"song_title", "song_title", "${currentMediaItem?.mediaMetadata?.title}"
"${currentMediaItem?.mediaMetadata?.title}"
) )
val songMap = mutableMapOf( val songMap = mutableMapOf(
Pair( Pair(
AnalysisUtil.PARAM_VALUE, AnalysisUtil.PARAM_VALUE, jsonObject.toString()
jsonObject.toString()
) )
) )
val currentFavoriteBean = val currentFavoriteBean =
@ -224,13 +220,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean) App.appFavoriteDBManager.updateFavoriteBean(currentFavoriteBean)
if (currentFavoriteBean.isFavorite) { if (currentFavoriteBean.isFavorite) {
AnalysisUtil.logEvent( AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_LOVE_CLICK, AnalysisUtil.PLAYER_B_LOVE_CLICK, songMap
songMap
) )
} else { } else {
AnalysisUtil.logEvent( AnalysisUtil.logEvent(
AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, AnalysisUtil.PLAYER_B_UN_LOVE_CLICK, songMap
songMap
) )
} }
} else { } else {
@ -243,27 +237,23 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
is Request.OnDownload -> { is Request.OnDownload -> {
LolAdWrapper.shared.showAdTiming( LolAdWrapper.shared.showAdTiming(
this@MoPlayDetailsActivity, this@MoPlayDetailsActivity, AdPlacement.INST_DOWNLOAD
AdPlacement.INST_DOWNLOAD
) )
insertOfflineData(it.mediaItem) insertOfflineData(it.mediaItem)
val jsonObject = JSONObject() val jsonObject = JSONObject()
jsonObject.put( jsonObject.put(
"download_id", "download_id", "${it.mediaItem.mediaId}"
"${it.mediaItem.mediaId}"
) )
val songMap = mutableMapOf( val songMap = mutableMapOf(
Pair( Pair(
AnalysisUtil.PARAM_VALUE, AnalysisUtil.PARAM_VALUE, jsonObject.toString()
jsonObject.toString()
) )
) )
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap) AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap)
LolAdWrapper.shared.loadAdIfNotCached( LolAdWrapper.shared.loadAdIfNotCached(
this@MoPlayDetailsActivity, this@MoPlayDetailsActivity, AdPlacement.INST_DOWNLOAD
AdPlacement.INST_DOWNLOAD
) )
} }
@ -327,13 +317,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
val jsonObject = JSONObject() val jsonObject = JSONObject()
jsonObject.put( jsonObject.put(
"download_id", "download_id", download.request.id
download.request.id
) )
val songMap = mutableMapOf( val songMap = mutableMapOf(
Pair( Pair(
AnalysisUtil.PARAM_VALUE, AnalysisUtil.PARAM_VALUE, jsonObject.toString()
jsonObject.toString()
) )
) )
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_SUCCESS_ACTION, songMap) AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_SUCCESS_ACTION, songMap)
@ -434,15 +422,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
private fun initPlayListAdapter() { private fun initPlayListAdapter() {
playListAdapter = PlayListAdapter( playListAdapter = PlayListAdapter(
this@MoPlayDetailsActivity, this@MoPlayDetailsActivity, playList
playList )
binding.playListRv.layoutManager = LinearLayoutManager(
this@MoPlayDetailsActivity, LinearLayoutManager.VERTICAL, false
) )
binding.playListRv.layoutManager =
LinearLayoutManager(
this@MoPlayDetailsActivity,
LinearLayoutManager.VERTICAL,
false
)
binding.playListRv.adapter = playListAdapter binding.playListRv.adapter = playListAdapter
} }
@ -564,18 +548,20 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
return@setOnClickListener return@setOnClickListener
} }
val downloadRequest = DownloadRequest val downloadRequest = DownloadRequest.Builder(contentId, contentId.toUri())
.Builder(contentId, contentId.toUri()) .setCustomCacheKey(contentId).build()
.setCustomCacheKey(contentId)
.build()
DownloadService.sendAddDownload(
this,
MyDownloadService::class.java,
downloadRequest,
false
)
requests.trySend(Request.OnDownload(currentMediaItem!!)) val downloadCount = DownloadUtil.getCurrentDownloads()
if (downloadCount >= 3) {
Toast.makeText(this, getString(R.string.download_tips), Toast.LENGTH_LONG)
.show()
} else {
DownloadService.sendAddDownload(
this, MyDownloadService::class.java, downloadRequest, false
)
requests.trySend(Request.OnDownload(currentMediaItem!!))
}
} }
} }
} }
@ -611,10 +597,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
parameters: String? = null parameters: String? = null
) { ) {
SongRadio( SongRadio(
videoId, videoId, playlistId, playlistSetVideoId, parameters
playlistId,
playlistSetVideoId,
parameters
).let { ).let {
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
val songRadioList = it.process()//获取到的资源集合 val songRadioList = it.process()//获取到的资源集合
@ -647,15 +630,10 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.totalDurationTv.visibility = View.GONE binding.totalDurationTv.visibility = View.GONE
val newMediaItem = val newMediaItem = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
MediaItem.Builder() .setCustomCacheKey(videoId).setMediaMetadata(
.setMediaId(videoId) mediaItem.mediaMetadata
.setUri(videoId) ).build()
.setCustomCacheKey(videoId)
.setMediaMetadata(
mediaItem.mediaMetadata
)
.build()
meController?.let { meController?.let {
it.setMediaItem(newMediaItem, true) it.setMediaItem(newMediaItem, true)
@ -679,14 +657,10 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
private val playerListener = object : Player.Listener { private val playerListener = object : Player.Listener {
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
override fun onPositionDiscontinuity( override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo, oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, reason: Int
newPosition: Player.PositionInfo,
reason: Int
) { ) {
//保证自动播放完毕当前歌曲与通知切换歌曲可以更新UI信息 //保证自动播放完毕当前歌曲与通知切换歌曲可以更新UI信息
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION || reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT) {
|| reason == Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT
) {
updateProgressUi() updateProgressUi()
updateInfoUi(meController?.currentMediaItem) updateInfoUi(meController?.currentMediaItem)
if (playListAdapter != null) { if (playListAdapter != null) {
@ -703,8 +677,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
} }
override fun onPlayWhenReadyChanged( override fun onPlayWhenReadyChanged(
playWhenReady: Boolean, playWhenReady: Boolean, reason: Int
reason: Int
) { ) {
updatePlayState(playWhenReady) updatePlayState(playWhenReady)
updateProgressState() updateProgressState()
@ -732,14 +705,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.loadingView.visibility = View.GONE binding.loadingView.visibility = View.GONE
binding.disableClicksLayout.visibility = View.GONE binding.disableClicksLayout.visibility = View.GONE
binding.totalDurationTv.visibility = View.VISIBLE binding.totalDurationTv.visibility = View.VISIBLE
binding.totalDurationTv.text = binding.totalDurationTv.text = convertMillisToMinutesAndSecondsString(
convertMillisToMinutesAndSecondsString( MediaControllerManager.getDuration()
MediaControllerManager.getDuration() )
) binding.sbProgress.valueTo = MediaControllerManager.getDuration().toFloat()
binding.sbProgress.valueTo = binding.progressBar.max = MediaControllerManager.getDuration().toInt()
MediaControllerManager.getDuration().toFloat()
binding.progressBar.max =
MediaControllerManager.getDuration().toInt()
updateProgressBufferingState() updateProgressBufferingState()
} }
@ -779,11 +749,8 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
} }
Glide.with(this) Glide.with(this).asBitmap().load(mediaItem.mediaMetadata.artworkUri)
.asBitmap() .placeholder(R.mipmap.app_logo).into(object : CustomTarget<Bitmap>() {
.load(mediaItem.mediaMetadata.artworkUri)
.placeholder(R.mipmap.app_logo)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
binding.thumbnail.setImageBitmap(resource) binding.thumbnail.setImageBitmap(resource)
val blurredBitmap = applyGaussianBlur(resource, 25f, this@MoPlayDetailsActivity) val blurredBitmap = applyGaussianBlur(resource, 25f, this@MoPlayDetailsActivity)

View File

@ -205,6 +205,14 @@ object DownloadUtil {
return downloadManager return downloadManager
} }
fun getCurrentDownloads(): Int {
val currentDownloads = downloadManager?.currentDownloads
if (currentDownloads != null) {
return currentDownloads.size
}
return 0
}
@Synchronized @Synchronized
private fun ensureDownloadManagerInitialized(context: Context) { private fun ensureDownloadManagerInitialized(context: Context) {
if (downloadManager == null) { if (downloadManager == null) {

View File

@ -174,6 +174,30 @@
android:textColor="@color/white_60" android:textColor="@color/white_60"
android:textSize="12dp" /> android:textSize="12dp" />
<LinearLayout
android:id="@+id/play_all_btn"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="8dp"
android:background="@drawable/drw_btn_bg"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:fontFamily="@font/medium_font"
android:text="@string/play"
android:textColor="@color/black"
android:textSize="16dp" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -38,4 +38,6 @@
<string name="offline_songs_no_data_prompt">You haven\'t saved any songs for offline listening yet.</string> <string name="offline_songs_no_data_prompt">You haven\'t saved any songs for offline listening yet.</string>
<string name="no_data_prompt_dialog_content">It looks like there\'s no data. Please add some and try again.</string> <string name="no_data_prompt_dialog_content">It looks like there\'s no data. Please add some and try again.</string>
<string name="prompt">Prompt</string> <string name="prompt">Prompt</string>
<string name="play">PLAY</string>
<string name="download_tips">There are additional download tasks in progress, please wait a moment.</string>
</resources> </resources>