From 641e789e2c2db1f59cbb9d3588d0a02987c77036 Mon Sep 17 00:00:00 2001 From: ocean <503259349@qq.com> Date: Tue, 25 Jun 2024 10:46:31 +0800 Subject: [PATCH] update --- app/build.gradle.kts | 24 +-- .../offline/music/activity/MoBaseActivity.kt | 76 +++++----- .../music/activity/MoLikedSongsActivity.kt | 141 ++++++++++++++++-- .../music/database/AppOfflineDBManager.kt | 4 + .../main/res/drawable/more_download_icon.xml | 4 +- 5 files changed, 184 insertions(+), 65 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3855ac4..3c6cbe3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -124,16 +124,16 @@ dependencies { implementation("com.google.ads.mediation:ironsource:8.1.0.0") //max - implementation("com.applovin:applovin-sdk:12.5.0") - implementation("com.applovin.mediation:google-adapter:22.1.0.0") - implementation("com.applovin.mediation:facebook-adapter:6.11.0.5") - implementation("com.applovin.mediation:adcolony-adapter:4.8.0.2") - implementation("com.applovin.mediation:vungle-adapter:6.12.0.0") - implementation("com.applovin.mediation:bytedance-adapter:4.7.0.8.0") - implementation("com.applovin.mediation:mintegral-adapter:16.2.31.0") - implementation("androidx.recyclerview:recyclerview:1.3.2")//mintegral 需要 - implementation("com.applovin.mediation:unityads-adapter:4.4.1.0") - implementation("com.applovin.mediation:smaato-adapter:21.8.5.0") - implementation("com.applovin.mediation:tapjoy-adapter:12.11.0.0") - implementation("com.applovin.mediation:ironsource-adapter:7.3.1.1.0") +// implementation("com.applovin:applovin-sdk:12.5.0") +// implementation("com.applovin.mediation:google-adapter:22.1.0.0") +// implementation("com.applovin.mediation:facebook-adapter:6.11.0.5") +// implementation("com.applovin.mediation:adcolony-adapter:4.8.0.2") +// implementation("com.applovin.mediation:vungle-adapter:6.12.0.0") +// implementation("com.applovin.mediation:bytedance-adapter:4.7.0.8.0") +// implementation("com.applovin.mediation:mintegral-adapter:16.2.31.0") +// implementation("androidx.recyclerview:recyclerview:1.3.2")//mintegral 需要 +// implementation("com.applovin.mediation:unityads-adapter:4.4.1.0") +// implementation("com.applovin.mediation:smaato-adapter:21.8.5.0") +// implementation("com.applovin.mediation:tapjoy-adapter:12.11.0.0") +// implementation("com.applovin.mediation:ironsource-adapter:7.3.1.1.0") } \ No newline at end of file diff --git a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt index caa6047..2a1dc3b 100644 --- a/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/MoBaseActivity.kt @@ -37,18 +37,16 @@ import melody.offline.music.media.MediaControllerManager import melody.offline.music.sp.AppStore import melody.offline.music.util.LogTag import melody.offline.music.http.getCountryCode +import melody.offline.music.util.DownloadUtil +import melody.offline.music.util.FileSizeConverter import melody.offline.music.view.MusicPlayerView @OptIn(UnstableApi::class) -abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), - LifecycleOwner { +abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), LifecycleOwner { private var playerListener: Player.Listener? = null enum class Event { - ActivityStart, - ActivityStop, - ActivityOnResume, - AutomaticallySwitchSongs, + ActivityStart, ActivityStop, ActivityOnResume, AutomaticallySwitchSongs, } protected val TAG = LogTag.VO_ACT_LOG @@ -142,9 +140,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope playerListener = object : Player.Listener { override fun onPositionDiscontinuity( - oldPosition: Player.PositionInfo, - newPosition: Player.PositionInfo, - reason: Int + oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, reason: Int ) { if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) { if (meController != null) { @@ -182,8 +178,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope } override fun onPlayWhenReadyChanged( - playWhenReady: Boolean, - reason: Int + playWhenReady: Boolean, reason: Int ) { LogTag.LogD(TAG, "base onPlayWhenReadyChanged $playWhenReady") musicPlayerView.updatePlayState(playWhenReady) @@ -221,8 +216,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope val content = dialogView.findViewById(R.id.dialog_content) content.text = description val close = dialogView.findViewById(R.id.closeBtn) - val dialogBuilder = AlertDialog.Builder(this) - .setView(dialogView) + val dialogBuilder = AlertDialog.Builder(this).setView(dialogView) val dialog = dialogBuilder.create() dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) dialog.show() @@ -251,6 +245,35 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope App.appOfflineDBManager.insertOfflineBean(bean) } + suspend fun insertOfflineData(favoriteBean: FavoriteBean) { + val currentDownload = DownloadUtil.getCurrentIdDownload(favoriteBean.videoId) + if (currentDownload != null) { + val bytesDownloaded = currentDownload.bytesDownloaded + val size = FileSizeConverter(currentDownload.bytesDownloaded).formattedSize() + val bean = OfflineBean( + videoId = favoriteBean.videoId, + title = favoriteBean.title, + name = favoriteBean.name, + thumbnail = favoriteBean.thumbnail, + isOffline = true, + isFavorite = favoriteBean.isFavorite, + bytesDownloaded = bytesDownloaded, + size = size + ) + App.appOfflineDBManager.insertOfflineBean(bean) + } else { + val bean = OfflineBean( + videoId = favoriteBean.videoId, + title = favoriteBean.title, + name = favoriteBean.name, + thumbnail = favoriteBean.thumbnail, + isOffline = true, + isFavorite = favoriteBean.isFavorite, + ) + App.appOfflineDBManager.insertOfflineBean(bean) + } + } + suspend fun insertFavoriteData(mediaItem: MediaItem) { val bean = FavoriteBean( videoId = mediaItem.mediaId, @@ -296,15 +319,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope // 不允许的国家代码 val restrictedCountries = setOf( // "CN", - "HK", - "TW", - "JP", - "KR", - "GB", - "CH", - "BE", - "MO", - "SG" + "HK", "TW", "JP", "KR", "GB", "CH", "BE", "MO", "SG" ) // 检查是否包含当前的国家代码 LogTag.LogD(TAG, "withPermission ipCountryCode->${appStore.ipCountryCode}") @@ -326,22 +341,11 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope //206 Belgium //455 "Macao, China" //525 Singapore (Republic of) - val restrictedCountryCodes = - setOf( + val restrictedCountryCodes = setOf( // "460", // "461", - "454", - "466", - "440", - "441", - "450", - "234", - "235", - "228", - "206", - "455", - "525" - ) + "454", "466", "440", "441", "450", "234", "235", "228", "206", "455", "525" + ) val currentCountryCode = getCountryCode(this) LogTag.LogD(TAG, "withPermission currentCountryCode->${currentCountryCode}") return currentCountryCode !in restrictedCountryCodes diff --git a/app/src/main/java/melody/offline/music/activity/MoLikedSongsActivity.kt b/app/src/main/java/melody/offline/music/activity/MoLikedSongsActivity.kt index eaa2b5e..2da8de9 100644 --- a/app/src/main/java/melody/offline/music/activity/MoLikedSongsActivity.kt +++ b/app/src/main/java/melody/offline/music/activity/MoLikedSongsActivity.kt @@ -1,11 +1,20 @@ package melody.offline.music.activity import android.annotation.SuppressLint +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.view.LayoutInflater import android.view.View import android.view.animation.AnimationUtils +import android.widget.TextView +import android.widget.Toast import androidx.annotation.OptIn +import androidx.appcompat.app.AlertDialog +import androidx.core.net.toUri import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.offline.Download +import androidx.media3.exoplayer.offline.DownloadRequest +import androidx.media3.exoplayer.offline.DownloadService import androidx.recyclerview.widget.LinearLayoutManager import com.bumptech.glide.Glide import com.gyf.immersionbar.ktx.immersionBar @@ -18,8 +27,8 @@ import melody.offline.music.adapter.LikedSongsAdapter import melody.offline.music.ads.AdPlacement import melody.offline.music.ads.LolAdWrapper import melody.offline.music.bean.FavoriteBean -import melody.offline.music.bean.OfflineBean import melody.offline.music.databinding.ActivityLikedSongsBinding +import melody.offline.music.service.MyDownloadService import melody.offline.music.service.ViewModelMain import melody.offline.music.util.AnalysisUtil import melody.offline.music.util.DownloadUtil @@ -36,6 +45,9 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites data object TryAgain : Request() data class UpdateFavorite(val bean: FavoriteBean) : Request() data class OnFavorites(val bean: FavoriteBean) : Request() + data class OnDownload(val favoriteBean: FavoriteBean) : Request() + data class OnDownloadRemove(val id: String) : Request() + data class OnUpdateDownloadUi(val id: String) : Request() } private lateinit var binding: ActivityLikedSongsBinding @@ -51,6 +63,7 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites initView() initAdapter() LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST) + initDownloadFlow() initData() onReceive() } @@ -94,6 +107,88 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites App.appFavoriteDBManager.updateFavoriteBean(it.bean) } } + + is Request.OnDownload -> { + val id = it.favoriteBean.videoId + LogTag.LogD(TAG,"OnDownload id->${id}") + val currentOfflineBean = App.appOfflineDBManager.getOfflineBeanByID(id) + if (currentOfflineBean != null) {//判断当前数据库是否有这条数据。 + if (currentPosition >= 0) { + val videoId = favoriteBeans[currentPosition].videoId + showRemoveDownloadDialogHint(videoId) + } + } else { + //判断是否已经下载了这条数据,已经下载,就直接进行数据库数据存储,反之走下载流程。 + if (DownloadUtil.downloadResourceExist(id)) { + insertOfflineData(it.favoriteBean) + requests.trySend(Request.OnUpdateDownloadUi(id)) + } else { + val downloadRequest = DownloadRequest.Builder(id, id.toUri()) + .setCustomCacheKey(id).build() + + val downloadCount = DownloadUtil.getCurrentDownloads() + if (downloadCount >= 3) { + Toast.makeText( + this@MoLikedSongsActivity, + getString(R.string.download_tips), + Toast.LENGTH_LONG + ).show() + } else { + DownloadService.sendAddDownload( + this@MoLikedSongsActivity, + MyDownloadService::class.java, + downloadRequest, + false + ) + + + LolAdWrapper.shared.showAdTiming( + this@MoLikedSongsActivity, AdPlacement.INST_DOWNLOAD + ) + + insertOfflineData(it.favoriteBean) + val jsonObject = JSONObject() + jsonObject.put( + "download_id", "${it.favoriteBean.videoId}" + ) + val songMap = mutableMapOf( + Pair( + AnalysisUtil.PARAM_VALUE, jsonObject.toString() + ) + ) + AnalysisUtil.logEvent( + AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap + ) + + LolAdWrapper.shared.loadAdIfNotCached( + this@MoLikedSongsActivity, AdPlacement.INST_DOWNLOAD + ) + } + } + } + } + + is Request.OnDownloadRemove -> { + LogTag.LogD(TAG,"OnDownloadRemove id->${it.id}") + val currentOfflineBean = + App.appOfflineDBManager.getOfflineBeanByID(it.id) + if (currentOfflineBean != null) { + App.appOfflineDBManager.deleteOfflineBean(currentOfflineBean) + } + + requests.trySend(Request.OnUpdateDownloadUi(it.id)) + } + + is Request.OnUpdateDownloadUi -> { + if (App.appOfflineDBManager.getOfflineBeanByID(it.id) != null) { + binding.downloadImg.setImageResource(R.drawable.more_downloaded_icon) + binding.downloadTv.text = + getString(R.string.download_remove_offline) + } else { + binding.downloadImg.setImageResource(R.drawable.more_download_icon) + binding.downloadTv.text = getString(R.string.download_save_offline) + } + } } } events.onReceive { @@ -152,7 +247,27 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites } } binding.moreDownloadBtn.setOnClickListener { + if (currentPosition >= 0) { + requests.trySend(Request.OnDownload(favoriteBeans[currentPosition])) + } + } + } + private fun showRemoveDownloadDialogHint(id: String) { + val inflater = LayoutInflater.from(this) + val dialogView = inflater.inflate(R.layout.dialog_hint, null) + val okBtn = dialogView.findViewById(R.id.dialog_ok_btn) + val cancelBtn = dialogView.findViewById(R.id.dialog_cancel_btn) + val dialogBuilder = AlertDialog.Builder(this).setView(dialogView) + val dialog = dialogBuilder.create() + dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + dialog.show() + okBtn.setOnClickListener { + dialog.dismiss() + requests.trySend(Request.OnDownloadRemove(id)) + } + cancelBtn.setOnClickListener { + dialog.dismiss() } } @@ -175,8 +290,8 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites private fun initDownloadFlow() { ViewModelMain.modelDownloadsFlow.observe(this) { downloads -> - if (meController != null && meController.currentMediaItem != null) { - val id = meController.currentMediaItem?.mediaId + if (currentPosition >= 0) { + val id = favoriteBeans[currentPosition].videoId val currentScreenDownloads = downloads[id] if (currentScreenDownloads != null) { updateDownloadUI(currentScreenDownloads) @@ -205,6 +320,9 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites binding.downloadTv.text = getString(R.string.download_remove_offline) + binding.moreDownloadBtn.isClickable = true + binding.moreDownloadBtn.isEnabled = true + val jsonObject = JSONObject() jsonObject.put( "download_id", download.request.id @@ -273,18 +391,11 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites } requests.trySend(Request.UpdateFavorite(bean)) - if (DownloadUtil.downloadResourceExist(bean.videoId)) {//已经下载,按钮不可点击 - binding.downloadImg.setImageResource(R.drawable.more_downloaded_icon) - binding.moreDownloadBtn.isClickable = false - binding.moreDownloadBtn.isEnabled = false - binding.downloadTv.text = getString(R.string.download_remove_offline) - } else { - binding.downloadLoading.visibility = View.GONE - binding.downloadImg.setImageResource(R.drawable.more_download_icon) - binding.downloadImg.visibility = View.VISIBLE - binding.moreDownloadBtn.isClickable = true - binding.moreDownloadBtn.isEnabled = true - binding.downloadTv.text = getString(R.string.download_save_offline) + requests.trySend(Request.OnUpdateDownloadUi(bean.videoId)) + + val currentDownload = DownloadUtil.getCurrentIdDownload(bean.videoId) + if (currentDownload != null) { + updateDownloadUI(currentDownload) } } diff --git a/app/src/main/java/melody/offline/music/database/AppOfflineDBManager.kt b/app/src/main/java/melody/offline/music/database/AppOfflineDBManager.kt index 5ed211f..4445c81 100644 --- a/app/src/main/java/melody/offline/music/database/AppOfflineDBManager.kt +++ b/app/src/main/java/melody/offline/music/database/AppOfflineDBManager.kt @@ -7,6 +7,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase import melody.offline.music.bean.OfflineBean import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import melody.offline.music.util.LogTag class AppOfflineDBManager private constructor(context: Context) { @@ -36,10 +37,13 @@ class AppOfflineDBManager private constructor(context: Context) { suspend fun insertOfflineBean(bean: OfflineBean) { withContext(Dispatchers.IO) { + LogTag.LogD(LogTag.VO_TEST_ONLY, "insertOfflineBean bean.videoId->${bean.videoId}") val offlineBean = getOfflineBeanByID(bean.videoId) if (offlineBean == null) { + LogTag.LogD(LogTag.VO_TEST_ONLY, "insertOfflineBean 1") dao.insertOfflineBean(bean) } else { + LogTag.LogD(LogTag.VO_TEST_ONLY, "insertOfflineBean 2") dao.updateOfflineBean(bean) } } diff --git a/app/src/main/res/drawable/more_download_icon.xml b/app/src/main/res/drawable/more_download_icon.xml index 3bd2729..f51f214 100644 --- a/app/src/main/res/drawable/more_download_icon.xml +++ b/app/src/main/res/drawable/more_download_icon.xml @@ -15,13 +15,13 @@ android:strokeLineJoin="round" android:strokeWidth="1.5" android:fillColor="#00000000" - android:strokeColor="#80F988" + android:strokeColor="#ffffff" android:strokeLineCap="round"/>