This commit is contained in:
ocean 2024-06-14 18:50:50 +08:00
parent b040a1d9c1
commit 08c7dd3ccc
19 changed files with 1049 additions and 69 deletions

View File

@ -61,7 +61,7 @@ dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.media3:media3-session:1.3.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.2")

View File

@ -33,6 +33,7 @@ import melody.offline.music.util.AppLifecycleHandler
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicLong
@OptIn(UnstableApi::class)
class App : Application() {
@ -118,6 +119,8 @@ class App : Application() {
var isAdShowing: AtomicBoolean = AtomicBoolean(false)//是否正在广告界面
var lastAdDisplayTime: AtomicLong = AtomicLong(0L)//上次广告展示的时间
override fun onCreate() {
super.onCreate()
AnalysisUtil.logEvent(AnalysisUtil.USER_LAUNCH)

View File

@ -87,23 +87,27 @@ class LaunchActivity : MoBaseActivity() {
}
private fun toMainActivity() {
if (!withPermission()) {
startActivity(Intent(this, MainActivity::class.java))
} else {
// if (!withPermission()) {
// startActivity(Intent(this, MainActivity::class.java))
// } else {
startActivity(Intent(this, PrimaryActivity::class.java))
}
// }
AnalysisUtil.logEvent(AnalysisUtil.LAUNCH_PV)
finish()
}
private fun loadAd() {
LolAdWrapper.shared.loadAd(this,
LolAdWrapper.shared.loadAd(
this,
AdPlacement.INST_SPLASH,
object : LolAdWrapper.LoLLoadListener {
override fun loadFailed(error: LolLoadError?) {
handler.sendEmptyMessage(MSG_LOAD_AD_FAIL)
}
})
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_BACKUP_ADS)
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_INTO_PLAY)
}
private fun adCanShow(): Boolean {
@ -111,7 +115,8 @@ class LaunchActivity : MoBaseActivity() {
}
private fun showAd() {
LolAdWrapper.shared.showAdIfCached(this,
LolAdWrapper.shared.showAdIfCached(
this,
AdPlacement.INST_SPLASH,
object : LolAdWrapper.LolShowListener {
override fun closed() {

View File

@ -13,6 +13,8 @@ import androidx.media3.common.Player
import com.bumptech.glide.Glide
import com.gyf.immersionbar.ktx.immersionBar
import melody.offline.music.R
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.Audio
import melody.offline.music.databinding.ActivityMainBinding
import melody.offline.music.fragment.HomeFragment
@ -31,17 +33,9 @@ class MainActivity : BaseActivity() {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// initImmersionBar()
initView()
}
private fun initImmersionBar() {
immersionBar {
statusBarDarkFont(false)
statusBarView(binding.view)
}
}
private fun initView() {
initClick()
initFragment()
@ -49,8 +43,12 @@ class MainActivity : BaseActivity() {
override fun onResume() {
super.onResume()
val currentPlayer = LocalMediaControllerManager.getController()
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_CUTTING_SONG)
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_DOWNLOAD)
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_SEARCH)
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
val currentPlayer = LocalMediaControllerManager.getController()
if (melody.offline.music.App.currentPlayingAudio == null) {
binding.playingStatusLayout.visibility = View.GONE
} else {

View File

@ -9,6 +9,8 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.App
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.databinding.ActivityLikedSongsBinding
@ -28,9 +30,11 @@ class MoLikedSongsActivity : MoBaseActivity(), LikedSongsAdapter.OnItemFavorites
override suspend fun main() {
binding = ActivityLikedSongsBinding.inflate(layoutInflater)
setContentView(binding.root)
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_ME_PAGE_LIST)
initImmersionBar()
initView()
initAdapter()
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
initData()
onReceive()
}

View File

@ -9,6 +9,8 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.App
import melody.offline.music.adapter.OfflineSongsAdapter
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.bean.OfflineBean
import melody.offline.music.databinding.ActivityOfflineSongsBinding
@ -26,9 +28,11 @@ class MoOfflineSongsActivity : MoBaseActivity() {
override suspend fun main() {
binding = ActivityOfflineSongsBinding.inflate(layoutInflater)
setContentView(binding.root)
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_ME_PAGE_LIST)
initImmersionBar()
initView()
initAdapter()
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_ME_PAGE_LIST)
initData()
onReceive()
}

View File

@ -43,6 +43,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select
import org.json.JSONObject
import melody.offline.music.App
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.util.AnalysisUtil
@OptIn(UnstableApi::class)
@ -86,6 +88,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
override suspend fun main() {
binding = ActivityMoPlayDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
showAD()
initImmersionBar()
initClick()
initPlayerListener()
@ -180,6 +183,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
params
)
}
loadAd()
initDownloadFlow()
onReceive()
}
@ -237,6 +241,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
}
is Request.OnDownload -> {
LolAdWrapper.shared.showAdTiming(
this@MoPlayDetailsActivity,
AdPlacement.INST_DOWNLOAD
)
insertOfflineData(it.mediaItem)
val jsonObject = JSONObject()
jsonObject.put(
@ -250,6 +259,11 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
)
)
AnalysisUtil.logEvent(AnalysisUtil.PLAYER_B_DOWNLOAD_CLICK, songMap)
LolAdWrapper.shared.loadAdIfNotCached(
this@MoPlayDetailsActivity,
AdPlacement.INST_DOWNLOAD
)
}
is Request.UpdateFavorite -> {
@ -488,6 +502,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
}
}
binding.playSkipBackBtn.setOnClickListener {
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_CUTTING_SONG)
if (meController != null) {
meController.seekToPreviousMediaItem()
updateProgressUi()
@ -498,8 +513,10 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
meController.play()
}
}
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_CUTTING_SONG)
}
binding.playSkipForwardBtn.setOnClickListener {
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_CUTTING_SONG)
if (meController != null) {
meController.seekToNextMediaItem()
updateProgressUi()
@ -510,6 +527,7 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
meController.play()
}
}
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_CUTTING_SONG)
}
binding.listLayoutBtn.setOnClickListener {
toggleBottomLayout()
@ -876,4 +894,12 @@ class MoPlayDetailsActivity : MoBaseActivity(), Player.Listener {
binding.bottomLayout.startAnimation(slideDownAnimation)
binding.bottomLayout.visibility = View.GONE
}
private fun loadAd() {
LolAdWrapper.shared.loadAdIfNotCached(this, AdPlacement.INST_INTO_PLAY)
}
private fun showAD() {
LolAdWrapper.shared.showAdTiming(this, AdPlacement.INST_INTO_PLAY)
}
}

View File

@ -2,4 +2,12 @@ package melody.offline.music.ads
object AdPlacement {
const val INST_SPLASH = "inst_splash"//启动页广告
const val INST_SEARCH = "inst_search"//搜索广告
const val NATIVE_SEARCH = "native_search"//搜索原生
const val INST_INTO_PLAY = "inst_into_play"//进入播放
const val INST_CUTTING_SONG = "inst_cutting_song"//主动切歌
const val INST_DOWNLOAD = "inst_download"//下载歌曲
const val INST_ME_PAGE_LIST = "inst_me_page_list"//我的界面的内容跳转
const val NATIVE_ME_PAGE_LIST = "native_me_page_list"//我的界面的内容原生
const val INST_BACKUP_ADS = "inst_backup_ads"
}

View File

@ -1,13 +1,21 @@
package melody.offline.music.ads
import android.app.Activity
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.gms.ads.nativead.NativeAdView
import com.lol.apex.ok.google.adlibrary.base.listener.AdLoadListener
import com.lol.apex.ok.google.adlibrary.base.listener.AdShowListener
import com.lol.apex.ok.google.adlibrary.base.listener.LolLoadError
import com.lol.apex.ok.google.adlibrary.base.listener.LolShowError
import com.lol.apex.ok.google.adlibrary.inner.LOLAdsInnerDispatcher
import com.lol.apex.ok.google.adlibrary.inner.base.AdInnerLoadAdapter
import com.lol.apex.ok.google.adlibrary.inner.base.AdInnerShowAdapter
import com.lol.apex.ok.google.adlibrary.inst.LOLAdsInstDispatcher
import com.lol.apex.ok.google.adlibrary.rewarded.LOLAdsRewardedDispatcher
import melody.offline.music.App
import melody.offline.music.R
import melody.offline.music.sp.AppStore
import melody.offline.music.util.AnalysisUtil
class LolAdWrapper {
@ -74,7 +82,7 @@ class LolAdWrapper {
loadAd(act, placement, listener)
}
fun showAd(act: Activity, placement: String, listener: LolShowListener? = null) {
private fun showAd(act: Activity, placement: String, listener: LolShowListener? = null) {
if (act.isFinishing) return
LOLAdsInstDispatcher.getShower(act, placement, object : AdShowListener {
override fun onAdClicked() {
@ -99,6 +107,9 @@ class LolAdWrapper {
App.app.isAdShowing.set(true)
listener?.shown()
AnalysisUtil.placeToLogEvent(placement, AnalysisAdState.AD_SHOWN)
App.app.lastAdDisplayTime.set(System.currentTimeMillis())
}
override fun onAfterClickClosed() {}
@ -117,5 +128,68 @@ class LolAdWrapper {
showAd(act, placement, listener)
}
}
fun showAdTiming(act: Activity, placement: String, listener: LolShowListener? = null) {
//当前时间减去旧时间,才展示广告
if (System.currentTimeMillis() - App.app.lastAdDisplayTime.get() >= AppStore(App.app).showAdIntervalTime) {
showAdIfCached(act, placement, listener)
}
}
fun loadAdShowNativeAd(
context: Activity, nativeId: String, frameAd: FrameLayout, admobLayout: Int, maxLayout: Int
) {
val inner = LOLAdsInnerDispatcher(context, object : AdInnerLoadAdapter() {
//设置广告位
override fun getPlace(): String {
return nativeId
}
//设置admob的native广告布局
override fun getAdmobLayoutResId(): Int {
return admobLayout
}
override fun getMaxLayoutResId(): Int {
return maxLayout
}
})
inner.addAdLoadListener(object : AdLoadListener {
override fun onAdLoadFailed(error: LolLoadError?) {
}
override fun onAdLoaded() {
}
})
//广告展示监听回调
inner.addAdShowListener(object : AdShowListener {
override fun onAdClicked() {
}
override fun onAdRewarded() {
}
override fun onAdShowFailed(error: LolShowError?) {
}
override fun onAdShown() {}
override fun onAdClosed() {}
override fun onAfterClickClosed() {}
override fun onDelayClosed() {}
})
inner.loadAd2Show(object : AdInnerShowAdapter() {
override fun getAdContainer(): FrameLayout {
return frameAd
}
})
}
}

View File

@ -10,6 +10,9 @@ object Constants {
}
"""
const val KEY_SHOW_AD_INTERVAL_TIME = "key_show_ad_interval_time"
const val DEFAULT_SHOW_AD_INTERVAL_TIME = 1000 * 30L
const val KEY_AD_JSON = "music_key_ad_json"
const val DEFAULT_AD_JSON = """
{
@ -64,6 +67,356 @@ object Constants {
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_inst_search": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_native_search": {
"data": [{
"config": [
[
"admob_native",
{
"ca-app-pub-3940256099942544/2247696110": 100
}
]
],
"block": {
"admob_native": {
"delay": 0,
"rate": 0
},
"max_native": {
"delay": 0,
"rate": 0
}
},
"click": {
"admob_native": [
100,
100,
100,
100,
100
],
"max_native": [
100,
100,
100,
100,
100
]
},
"after_click": {
"admob_native": "next",
"max_native": "next"
},
"limit": {
"admob_native": 100,
"max_native": 100
}
}]
},
"Music_inst_into_play": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_inst_cutting_song": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_inst_download": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_inst_me_page_list": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
},
"Music_native_me_page_list": {
"data": [{
"config": [
[
"admob_native",
{
"ca-app-pub-3940256099942544/2247696110": 100
}
]
],
"block": {
"admob_native": {
"delay": 0,
"rate": 0
},
"max_native": {
"delay": 0,
"rate": 0
}
},
"click": {
"admob_native": [
100,
100,
100,
100,
100
],
"max_native": [
100,
100,
100,
100,
100
]
},
"after_click": {
"admob_native": "next",
"max_native": "next"
},
"limit": {
"admob_native": 100,
"max_native": 100
}
}]
},
"Music_inst_backup_ads": {
"data": [{
"after_click": {
"admob_inst": "keep",
"max_inst": "keep"
},
"block": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"close": {
"admob_inst": {
"delay": 0,
"rate": 0
},
"max_inst": {
"delay": 0,
"rate": 0
}
},
"config": [
[
"admob_inst",
{
"ca-app-pub-3940256099942544/1033173712": 100
}
]
],
"limit": {
"admob_inst": 100,
"max_inst": 100
},
"cycle": 0,
"timeout": 15000,
"showIntervalEnable": false
}]
}
}
"""

View File

@ -13,6 +13,8 @@ import melody.offline.music.R
import melody.offline.music.activity.MoLikedSongsActivity
import melody.offline.music.activity.MoOfflineSongsActivity
import melody.offline.music.activity.SettingsActivity
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import melody.offline.music.databinding.FragmentMoMeBinding
import melody.offline.music.util.AnalysisUtil
@ -72,9 +74,7 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>() {
AnalysisUtil.logEvent(AnalysisUtil.ME_B_PV)
} else {
Toast.makeText(
activity,
getString(R.string.liked_songs_no_data_prompt),
Toast.LENGTH_LONG
activity, getString(R.string.liked_songs_no_data_prompt), Toast.LENGTH_LONG
).show()
}
}
@ -86,9 +86,7 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>() {
AnalysisUtil.logEvent(AnalysisUtil.ME_B_PV)
} else {
Toast.makeText(
activity,
getString(R.string.offline_songs_no_data_prompt),
Toast.LENGTH_LONG
activity, getString(R.string.offline_songs_no_data_prompt), Toast.LENGTH_LONG
).show()
}
}
@ -104,6 +102,14 @@ class MoMeFragment : MoBaseFragment<FragmentMoMeBinding>() {
val favoriteBeans = App.appFavoriteDBManager.getAllFavoriteBeans()
val favorites = favoriteBeans.count { it.isFavorite }
binding.likedSongsTv.text = "$favorites"
LolAdWrapper.shared.loadAdShowNativeAd(
requireActivity(),
AdPlacement.NATIVE_ME_PAGE_LIST,
binding.frameAd,
R.layout.ad_layout_admob_result,
R.layout.ad_layout_max_result
)
}
override fun onResume() {

View File

@ -34,6 +34,8 @@ import melody.offline.music.view.SearchResultOtherView
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.selects.select
import melody.offline.music.ads.AdPlacement
import melody.offline.music.ads.LolAdWrapper
import org.json.JSONObject
import melody.offline.music.util.AnalysisUtil
@ -99,16 +101,13 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
SearchSuggestionsAdapter(requireActivity(), searchSuggestionsList)
searchSuggestionsAdapterAdapter?.setOnItemClickListener(this)
binding.searchSuggestionsRv.layoutManager = LinearLayoutManager(
requireActivity(),
LinearLayoutManager.VERTICAL,
false
requireActivity(), LinearLayoutManager.VERTICAL, false
)
binding.searchSuggestionsRv.adapter = searchSuggestionsAdapterAdapter
}
private fun initSearchHistoryAdapter() {
searchHistoryAdapter =
SearchHistoryAdapter(requireActivity(), searchHistory)
searchHistoryAdapter = SearchHistoryAdapter(requireActivity(), searchHistory)
searchHistoryAdapter?.setOnItemClickListener(this)
val layoutManager = FlexboxLayoutManager(requireActivity())
layoutManager.flexWrap = FlexWrap.WRAP // 设置换行方式为自动换行
@ -167,6 +166,9 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
}
is Request.SearchData -> {
LolAdWrapper.shared.showAdTiming(
requireActivity(), AdPlacement.INST_SEARCH
)
showLoadingLayout()
binding.contentLayout.removeAllViews()
binding.searchEdit.clearFocus()
@ -189,16 +191,14 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
if (dataPage.type == 1) {//type为1的是最佳结果。
binding.contentLayout.addView(
SearchResultOptimalView(
requireActivity(),
dataPage
requireActivity(), dataPage
)
)
} else if (dataPage.type == 2) {//type为2的是其他搜索结果。
if (dataPage.searchResultList.isNotEmpty()) {//如何数据集合为空就不添加view
binding.contentLayout.addView(
SearchResultOtherView(
requireActivity(),
dataPage
requireActivity(), dataPage
)
)
}
@ -208,6 +208,9 @@ class SearchFragment : MoBaseFragment<FragmentSearchBinding>(), TextWatcher,
showNoContentLayout()
}
}
LolAdWrapper.shared.loadAdIfNotCached(
requireActivity(), AdPlacement.INST_SEARCH
)
}
}
}

View File

@ -8,49 +8,39 @@ import melody.offline.music.util.PlayMode
class AppStore(context: Context) {
private val store = Store(
context
.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
.asStoreProvider()
context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE).asStoreProvider()
)
var searchHistoryStore: Set<String> by store.stringSet(
key = SEARCH_HISTORY,
defaultValue = emptySet()
key = SEARCH_HISTORY, defaultValue = emptySet()
)
var myVisitorData: String by store.string(
key = MY_VISITOR_DATA,
defaultValue = ""
key = MY_VISITOR_DATA, defaultValue = ""
)
var playMusicMode: Int by store.int(
key = PLAY_MUSIC_MODE,
defaultValue = PlayMode.LIST_LOOP.value
key = PLAY_MUSIC_MODE, defaultValue = PlayMode.LIST_LOOP.value
)
var userID: String by store.string(
key = APP_USERID,
defaultValue = ""
key = APP_USERID, defaultValue = ""
)
var appUUID: String by store.string(
key = APP_UUID,
defaultValue = ""
key = APP_UUID, defaultValue = ""
)
var ipCountryCode: String by store.string(
key = IP_COUNTRY_CODE,
defaultValue = ""
key = IP_COUNTRY_CODE, defaultValue = ""
)
var firstOpenIsSucceed: Boolean by store.boolean(
key = FIRST_OPEN_IS_SUCCEED,
defaultValue = false
key = FIRST_OPEN_IS_SUCCEED, defaultValue = false
)
var shouldEnterMusicPage: Boolean by store.boolean(
key = SHOULD_ENTER_MUSIC_PAGE,
defaultValue = true
key = SHOULD_ENTER_MUSIC_PAGE, defaultValue = true
)
var shouldEnterMusicPageJson: String by store.string(
@ -60,8 +50,13 @@ class AppStore(context: Context) {
//广告json-firebase配置
var adJson: String by store.string(
key = Constants.KEY_AD_JSON,
defaultValue = Constants.DEFAULT_AD_JSON
key = Constants.KEY_AD_JSON, defaultValue = Constants.DEFAULT_AD_JSON
)
//展示广告的间隔时间
var showAdIntervalTime: Long by store.long(
key = Constants.KEY_SHOW_AD_INTERVAL_TIME,
defaultValue = Constants.DEFAULT_SHOW_AD_INTERVAL_TIME
)
companion object {
@ -74,5 +69,6 @@ class AppStore(context: Context) {
const val IP_COUNTRY_CODE = "ip_country_code"
const val FIRST_OPEN_IS_SUCCEED = "first_open_is_succeed"
const val SHOULD_ENTER_MUSIC_PAGE = "key_should_enter_music_page"
}
}

View File

@ -33,9 +33,30 @@ object AnalysisUtil {
const val SEARCH_RESULT_SUCCESS_ACTION = "search_result_success_action"//搜索有结果
private const val AD_USER_OPEN_SUCCESS = "ad_user_open_success"//首页开屏广告展示成功
private const val AD_USER_OPEN_FAIL = "ad_user_open_fail"//首页开屏广告展示失败
private const val AD_USER_OPEN_LOAD_FAIL = "ad_user_open_load_fail"//首页开屏广告展示load失败
private const val AD_INST_SPLASH_SUCCESS = "ad_user_open_success"//首页开屏广告展示成功
private const val AD_INST_SPLASH_FAIL = "ad_user_open_fail"//首页开屏广告展示失败
private const val AD_INST_SPLASH_LOAD_FAIL = "ad_user_open_load_fail"//首页开屏广告展示load失败
private const val AD_INST_SEARCH_SUCCESS = "ad_inst_search_success"
private const val AD_INST_SEARCH_FAIL = "ad_inst_search_fail"
private const val AD_INST_SEARCH_LOAD_FAIL = "ad_inst_search_load_fail"
private const val AD_INST_INTO_PLAY_SUCCESS = "ad_inst_into_play_success"
private const val AD_INST_INTO_PLAY_FAIL = "ad_inst_into_play_fail"
private const val AD_INST_INTO_PLAY_LOAD_FAIL = "ad_inst_into_play_load_fail"
private const val AD_INST_CUTTING_SONG_SUCCESS = "ad_inst_cutting_song_success"
private const val AD_INST_CUTTING_SONG_FAIL = "ad_inst_cutting_song_fail"
private const val AD_INST_CUTTING_SONG_LOAD_FAIL = "ad_inst_cutting_song_load_fail"
private const val AD_INST_DOWNLOAD_SUCCESS = "ad_inst_download_success"
private const val AD_INST_DOWNLOAD_FAIL = "ad_inst_download_fail"
private const val AD_INST_DOWNLOAD_LOAD_FAIL = "ad_inst_download_load_fail"
private const val AD_INST_ME_PAGE_LIST_SUCCESS = "ad_inst_me_page_list_success"
private const val AD_INST_ME_PAGE_LIST_FAIL = "ad_inst_me_page_list_fail"
private const val AD_INST_ME_PAGE_LIST_LOAD_FAIL = "ad_inst_me_page_list_load_fail"
private var firebaseAnalytics: FirebaseAnalytics? = null
@ -76,15 +97,95 @@ object AnalysisUtil {
AdPlacement.INST_SPLASH -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_USER_OPEN_LOAD_FAIL, param)
logEvent(AD_INST_SPLASH_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_USER_OPEN_FAIL, param)
logEvent(AD_INST_SPLASH_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_USER_OPEN_SUCCESS)
logEvent(AD_INST_SPLASH_SUCCESS)
}
}
}
AdPlacement.INST_SEARCH -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_INST_SEARCH_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_INST_SEARCH_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_INST_SEARCH_SUCCESS)
}
}
}
AdPlacement.INST_INTO_PLAY -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_INST_INTO_PLAY_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_INST_INTO_PLAY_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_INST_INTO_PLAY_SUCCESS)
}
}
}
AdPlacement.INST_CUTTING_SONG -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_INST_CUTTING_SONG_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_INST_CUTTING_SONG_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_INST_CUTTING_SONG_SUCCESS)
}
}
}
AdPlacement.INST_DOWNLOAD -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_INST_DOWNLOAD_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_INST_DOWNLOAD_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_INST_DOWNLOAD_SUCCESS)
}
}
}
AdPlacement.INST_ME_PAGE_LIST -> {
when (state) {
AnalysisAdState.AD_LOAD_FAILED -> {
logEvent(AD_INST_ME_PAGE_LIST_LOAD_FAIL, param)
}
AnalysisAdState.AD_SHOW_FAILED -> {
logEvent(AD_INST_ME_PAGE_LIST_FAIL, param)
}
AnalysisAdState.AD_SHOWN -> {
logEvent(AD_INST_ME_PAGE_LIST_SUCCESS)
}
}
}

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="122dp"
android:background="@color/color_FFF1F1FB"
android:gravity="center_horizontal"
android:orientation="horizontal">
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/mv_event_con"
android:layout_width="148dp"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/im_event_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="40dp"
android:visibility="gone"
tools:background="@drawable/ic_launcher_background" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingHorizontal="12dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_event_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:drawableLeft="@mipmap/ad_tag"
android:drawablePadding="4dp"
android:ellipsize="end"
android:gravity="left"
android:lineSpacingExtra="0dp"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/theme_black"
android:textSize="16dp"
tools:text="dddd dddd dddd ddd " />
</LinearLayout>
<TextView
android:id="@+id/tv_event_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="left"
android:lineSpacingExtra="0dp"
android:maxLines="2"
android:minHeight="28dp"
android:textColor="@color/text_gray"
android:textSize="12dp"
tools:text="xxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:id="@+id/tv_event_bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="6dp"
android:background="@drawable/bg_btn_ad"
android:gravity="center"
android:minHeight="36dp"
android:textColor="@color/white"
android:textSize="14dp"
android:textStyle="bold"
tools:text="action now " />
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card_white_ad_round4dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/im_event_icon"
android:layout_width="46dp"
android:layout_height="46dp"
tools:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_event_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="4dp"
android:ellipsize="end"
android:drawableLeft="@mipmap/ad_tag"
android:fontFamily="@string/Roboto_Medium"
android:lineSpacingExtra="0dp"
android:paddingBottom="4dp"
android:singleLine="true"
android:textColor="@color/theme_black"
android:textSize="16dp"
android:textStyle="bold"
tools:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:id="@+id/tv_event_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@string/Roboto_Regular"
android:lineSpacingExtra="0dp"
android:maxLines="2"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textColor="@color/text_gray"
android:textSize="12dp"
tools:text="xxxxxxxxxxxxxxxxxxxxx" />
</LinearLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_marginHorizontal="12dp"
android:layout_height="wrap_content" >
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/mv_event_con"
android:layout_width="match_parent"
tools:background="@color/color_FFF7F9FB"
android:layout_height="152dp" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/tv_event_bt"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="10dp"
android:background="@drawable/bg_btn_ad"
android:textColor="@color/white"
android:textSize="15dp"
android:layout_marginBottom="12dp"
android:textStyle="bold"
tools:text="action now " />
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="122dp"
android:background="@color/color_FFF1F1FB"
android:gravity="center_horizontal"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<FrameLayout
android:id="@+id/mv_event_con"
android:layout_width="148dp"
tools:background="@color/white"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/im_event_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="40dp"
android:visibility="gone"
tools:background="@drawable/ic_launcher_background" />
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:paddingHorizontal="12dp"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_event_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:layout_marginLeft="4dp"
android:lineSpacingExtra="0dp"
android:drawablePadding="4dp"
android:drawableLeft="@mipmap/ad_tag"
android:singleLine="true"
android:gravity="left"
android:maxLines="1"
android:textColor="@color/theme_black"
android:textSize="16dp"
tools:text="dddd dddd dddd ddd " />
<LinearLayout
android:id="@+id/ll_ad_options_view"
android:layout_width="24dp"
android:layout_height="24dp"
android:orientation="vertical"
android:layout_marginStart="2dp"
android:visibility="gone"
android:layout_alignParentEnd="true">
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_event_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="28dp"
android:layout_marginTop="4dp"
android:gravity="left"
android:lineSpacingExtra="0dp"
android:maxLines="2"
android:textColor="@color/text_gray"
android:textSize="12dp"
tools:text="xxxxx xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:id="@+id/tv_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@string/Roboto_Regular"
android:layout_marginHorizontal="12dp"
android:textColor="@color/theme_black"
android:textSize="12dp"
android:visibility="gone"
tools:text="xxxxxxxxxxxxxxxxxxxxx" />
<Button
android:id="@+id/tv_event_bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="6dp"
android:gravity="center"
android:background="@drawable/bg_btn_ad"
android:textColor="@color/white"
android:textSize="14dp"
android:textStyle="bold"
tools:text="action now " />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card_white_ad_round4dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="12dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/im_event_icon"
android:layout_width="46dp"
android:layout_height="46dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="12dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_event_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="4dp"
android:ellipsize="end"
android:drawableLeft="@mipmap/ad_tag"
android:fontFamily="@string/Roboto_Medium"
android:lineSpacingExtra="0dp"
android:paddingBottom="4dp"
android:singleLine="true"
android:textColor="@color/theme_black"
android:textSize="16dp"
android:textStyle="bold"
tools:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<TextView
android:id="@+id/tv_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@string/Roboto_Regular"
android:textColor="@color/color_7f000000"
android:textSize="12dp"
android:visibility="visible"
tools:text="xxxxxxxxxxxxxxxxxxxxx" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_ad_options_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="-10dp"
android:visibility="visible"
android:layout_alignParentEnd="true">
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_event_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:fontFamily="@string/Roboto_Regular"
android:lineSpacingExtra="0dp"
android:maxLines="2"
android:layout_marginBottom="12dp"
android:layout_marginHorizontal="12dp"
android:textColor="@color/text_gray"
android:textSize="12dp"
tools:text="xxxxxxxxxxxxxxxxxxxxx" />
<FrameLayout
android:id="@+id/mv_event_con"
android:layout_width="match_parent"
android:layout_marginHorizontal="12dp"
tools:background="@color/color_FFF7F9FB"
android:layout_height="152dp" >
</FrameLayout>
<Button
android:id="@+id/tv_event_bt"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="10dp"
android:background="@drawable/bg_btn_ad"
android:textColor="@color/white"
android:textSize="15dp"
android:layout_marginBottom="12dp"
android:textStyle="bold"
tools:text="action now " />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -185,16 +185,11 @@
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="18dp"
android:visibility="gone"
android:fontFamily="@font/medium_font"
android:text="@string/new_playlist"
android:textColor="@color/white"
android:textSize="20dp" />
<FrameLayout
android:id="@+id/frame_ad"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>