This commit is contained in:
ocean 2024-06-25 10:46:31 +08:00
parent 44f827ba21
commit 641e789e2c
5 changed files with 184 additions and 65 deletions

View File

@ -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")
}

View File

@ -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<TextView>(R.id.dialog_content)
content.text = description
val close = dialogView.findViewById<RelativeLayout>(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

View File

@ -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<TextView>(R.id.dialog_ok_btn)
val cancelBtn = dialogView.findViewById<TextView>(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)
}
}

View File

@ -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)
}
}

View File

@ -15,13 +15,13 @@
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#80F988"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M18,8.5L12,14.5L6,8.5"
android:strokeLineJoin="round"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#80F988"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
</vector>