diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 12d9347..d459699 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -4,6 +4,8 @@ plugins {
id("kotlin-kapt")
id("org.jetbrains.kotlin.plugin.serialization")
id("kotlin-android")
+ id("com.google.gms.google-services")
+ id("com.google.firebase.crashlytics")
}
android {
@@ -30,13 +32,13 @@ android {
"proguard-rules.pro"
)
}
- debug {
- isMinifyEnabled = true
- proguardFiles(
- getDefaultProguardFile("proguard-android-optimize.txt"),
- "proguard-rules.pro"
- )
- }
+// debug {
+// isMinifyEnabled = true
+// proguardFiles(
+// getDefaultProguardFile("proguard-android-optimize.txt"),
+// "proguard-rules.pro"
+// )
+// }
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
@@ -97,4 +99,10 @@ dependencies {
//google
// implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
+
+ // Import the Firebase BoM
+ implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
+ implementation("com.google.firebase:firebase-analytics-ktx")
+ implementation("com.google.firebase:firebase-crashlytics-ktx")
+ implementation("com.google.firebase:firebase-config")
}
\ No newline at end of file
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..51665d3
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,29 @@
+{
+ "project_info": {
+ "project_number": "320083292372",
+ "project_id": "musiclax-and",
+ "storage_bucket": "musiclax-and.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:320083292372:android:047dd51c4c373acf9a8b41",
+ "android_client_info": {
+ "package_name": "relax.offline.mp3.music"
+ }
+ },
+ "oauth_client": [],
+ "api_key": [
+ {
+ "current_key": "AIzaSyCs8V_b7UYuUfcs_mAWIAbr06VZKBM-680"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": []
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4dc58cb..f7e56fd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -41,6 +41,7 @@
${bean}")
+ LogTag.LogD(TAG, "insertOfflineBean bean->${bean}")
App.appOfflineDBManager.insertOfflineBean(bean)
}
@@ -247,14 +245,30 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
thumbnail = mediaItem.mediaMetadata.artworkUri.toString(),
isFavorite = true
)
- LogTag.LogD(Innertube.TAG, "insertFavoriteBean bean->${bean}")
+ LogTag.LogD(TAG, "insertFavoriteBean bean->${bean}")
App.appFavoriteDBManager.insertFavoriteBean(bean)
}
fun withPermission(): Boolean {
+ //先判断当前配置的开关是否为true,为false的话就直接进入A
+ LogTag.LogD(TAG, "withPermission shouldEnterMusicPage->${appStore.shouldEnterMusicPage}")
+ if (!appStore.shouldEnterMusicPage) {
+ return false
+ }
// 不允许的国家代码
- val restrictedCountries = setOf("CN", "HK", "TW", "JP", "KR", "GB", "CH", "BE", "MO", "SG")
+ val restrictedCountries = setOf(
+// "CN",
+// "HK",
+ "TW",
+ "JP",
+ "KR",
+ "GB",
+ "CH",
+ "BE",
+ "MO",
+ "SG")
// 检查是否包含当前的国家代码
+ LogTag.LogD(TAG, "withPermission ipCountryCode->${appStore.ipCountryCode}")
if (appStore.ipCountryCode in restrictedCountries) {
return false
}
@@ -275,9 +289,9 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
//525 Singapore (Republic of)
val restrictedCountryCodes =
setOf(
- "460",
- "461",
- "454",
+// "460",
+// "461",
+// "454",
"466",
"440",
"441",
@@ -290,6 +304,7 @@ abstract class MoBaseActivity : AppCompatActivity(), CoroutineScope by MainScope
"525"
)
val currentCountryCode = getCountryCode(this)
+ LogTag.LogD(TAG, "withPermission currentCountryCode->${currentCountryCode}")
return currentCountryCode !in restrictedCountryCodes
}
}
\ No newline at end of file
diff --git a/app/src/main/java/relax/offline/music/database/AppOfflineDBManager.kt b/app/src/main/java/relax/offline/music/database/AppOfflineDBManager.kt
index 89faaa0..00d571a 100644
--- a/app/src/main/java/relax/offline/music/database/AppOfflineDBManager.kt
+++ b/app/src/main/java/relax/offline/music/database/AppOfflineDBManager.kt
@@ -31,10 +31,8 @@ class AppOfflineDBManager private constructor(context: Context) {
withContext(Dispatchers.IO) {
val offlineBean = getOfflineBeanByID(bean.videoId)
if (offlineBean == null) {
- LogTag.LogD(LogTag.VO_TEST_ONLY,"insertOfflineBean")
dao.insertOfflineBean(bean)
} else {
- LogTag.LogD(LogTag.VO_TEST_ONLY,"updateOfflineBean")
dao.updateOfflineBean(bean)
}
}
diff --git a/app/src/main/java/relax/offline/music/firebase/Constants.kt b/app/src/main/java/relax/offline/music/firebase/Constants.kt
new file mode 100644
index 0000000..8fb8267
--- /dev/null
+++ b/app/src/main/java/relax/offline/music/firebase/Constants.kt
@@ -0,0 +1,7 @@
+package relax.offline.music.firebase
+
+object Constants {
+ const val KEY_SHOULD_ENTER_MUSIC_PAGE = "key_should_enter_music_page"
+ const val DEFAULT_SHOULD_ENTER_MUSIC_PAGE = false
+}
+
diff --git a/app/src/main/java/relax/offline/music/firebase/RemoteConfig.kt b/app/src/main/java/relax/offline/music/firebase/RemoteConfig.kt
new file mode 100644
index 0000000..7946181
--- /dev/null
+++ b/app/src/main/java/relax/offline/music/firebase/RemoteConfig.kt
@@ -0,0 +1,146 @@
+package relax.offline.music.firebase
+
+import android.annotation.SuppressLint
+import android.app.Application
+import android.content.Context
+import android.os.Handler
+import android.os.Message
+import android.text.TextUtils
+import com.google.firebase.remoteconfig.ConfigUpdate
+import com.google.firebase.remoteconfig.ConfigUpdateListener
+import com.google.firebase.remoteconfig.FirebaseRemoteConfig
+import com.google.firebase.remoteconfig.FirebaseRemoteConfigException
+import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
+import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue
+import relax.offline.music.App
+import relax.offline.music.BuildConfig
+import relax.offline.music.sp.AppStore
+import relax.offline.music.util.LogTag
+import java.lang.ref.WeakReference
+
+class RemoteConfig {
+
+ private val TAG = LogTag.VO_TEST_ONLY
+ private var ctx: Context? = null
+ private var mFirebaseRemoteConfig: FirebaseRemoteConfig? = null
+
+ //配置是否初始化成功
+ private var isInit = false
+
+ //上次获取数据的时间
+ private var lastFetchTime: Long = 0
+ private val handler = MHandler(this)
+
+ companion object {
+ const val MSG_REFRESH_CONFIG = 1
+ val instance: RemoteConfig by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
+ RemoteConfig()
+ }
+ }
+
+ fun init(ctx: Application) {
+ this.ctx = ctx
+ initConfig()
+ fetchConfig()
+ onConfigUpdate()
+ }
+
+ private fun initConfig() {
+ var intervalTime = (60 * 10).toLong()
+ //如果是开发状态,则将提取时间缩短
+ if (BuildConfig.DEBUG) {
+ intervalTime = (60 * 5).toLong()
+ }
+ mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
+ val configSettings =
+ FirebaseRemoteConfigSettings.Builder() //默认值12小时的最短提取间隔,如果在间隔内取值,则优先取上次的结果
+ .setMinimumFetchIntervalInSeconds(intervalTime)
+ .build()
+ mFirebaseRemoteConfig!!.setConfigSettingsAsync(configSettings)
+ }
+
+ private fun onConfigUpdate() {
+ mFirebaseRemoteConfig!!.addOnConfigUpdateListener(object : ConfigUpdateListener {
+ override fun onUpdate(configUpdate: ConfigUpdate) {
+ LogTag.LogD(TAG, "Updated keys: " + configUpdate.updatedKeys)
+
+ if (configUpdate.updatedKeys.contains(Constants.KEY_SHOULD_ENTER_MUSIC_PAGE)) {
+ mFirebaseRemoteConfig!!.activate().addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ updateData("onConfigUpdate", mFirebaseRemoteConfig!!.all)
+ }
+ }
+ }
+ }
+
+ override fun onError(error: FirebaseRemoteConfigException) {
+ LogTag.LogD(TAG, "Config update error with code: " + error.code)
+ }
+ })
+ }
+
+ @SuppressLint("LongLogTag")
+ private fun fetchConfig() {
+ //这里可能会抛出异常 FirebaseRemoteConfigFetchThrottledException
+ try {
+ mFirebaseRemoteConfig!!.fetchAndActivate().addOnCompleteListener { task ->
+ if (task.isSuccessful) {
+ isInit = true
+ lastFetchTime = System.currentTimeMillis()
+ updateData("fetchAndActivate", mFirebaseRemoteConfig!!.all)
+ //24小时后,重新再去获取
+ handler.removeMessages(MSG_REFRESH_CONFIG)
+ handler.sendEmptyMessageDelayed(
+ MSG_REFRESH_CONFIG,
+ (1000 * 60 * 60 * 24).toLong()
+ )
+ } else {
+ //这里需要重新再去获取
+ handler.removeMessages(MSG_REFRESH_CONFIG)
+ handler.sendEmptyMessageDelayed(MSG_REFRESH_CONFIG, (1000 * 60 * 15).toLong())
+ }
+ }
+ } catch (ignore: Exception) {
+ }
+ }
+
+ private fun updateData(from: String, all: Map) {
+ val appStore = AppStore(App.app)
+ for ((key, value) in all) {
+ try {
+ LogTag.LogD(
+ TAG,
+ "from = " + from + "Key = " + key + " Value = " + value.asString()
+ )
+ if (TextUtils.equals(
+ Constants.KEY_SHOULD_ENTER_MUSIC_PAGE, key
+ )
+ ) {
+ val shouldEnterMusicPage = value.asBoolean()
+ appStore.shouldEnterMusicPage = shouldEnterMusicPage
+ }
+ } catch (ignore: Exception) {
+
+ }
+ }
+ }
+
+ private class MHandler(remoteConfig: RemoteConfig) : Handler() {
+ private val weakReference: WeakReference
+
+ init {
+ weakReference = WeakReference(remoteConfig)
+ }
+
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ val remoteConfig = weakReference.get()
+ if (remoteConfig?.ctx != null) {
+ if (msg.what == MSG_REFRESH_CONFIG) {
+ remoteConfig.fetchConfig()
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/relax/offline/music/sp/AppStore.kt b/app/src/main/java/relax/offline/music/sp/AppStore.kt
index c51e26c..b3fc26a 100644
--- a/app/src/main/java/relax/offline/music/sp/AppStore.kt
+++ b/app/src/main/java/relax/offline/music/sp/AppStore.kt
@@ -1,6 +1,7 @@
package relax.offline.music.sp
import android.content.Context
+import relax.offline.music.firebase.Constants
import relax.offline.music.sp.store.Store
import relax.offline.music.sp.store.asStoreProvider
import relax.offline.music.util.PlayMode
@@ -32,7 +33,7 @@ class AppStore(context: Context) {
defaultValue = ""
)
- var appUUID : String by store.string(
+ var appUUID: String by store.string(
key = APP_UUID,
defaultValue = ""
)
@@ -42,10 +43,16 @@ class AppStore(context: Context) {
defaultValue = ""
)
- var firstOpenIsSucceed : Boolean by store.boolean(
+ var firstOpenIsSucceed: Boolean by store.boolean(
key = FIRST_OPEN_IS_SUCCEED,
defaultValue = false
)
+
+ var shouldEnterMusicPage: Boolean by store.boolean(
+ key = Constants.KEY_SHOULD_ENTER_MUSIC_PAGE,
+ defaultValue = Constants.DEFAULT_SHOULD_ENTER_MUSIC_PAGE
+ )
+
companion object {
private const val FILE_NAME = "music_oo_app"
const val SEARCH_HISTORY = "search_history"
diff --git a/app/src/main/java/relax/offline/music/util/AnalysisUtil.kt b/app/src/main/java/relax/offline/music/util/AnalysisUtil.kt
new file mode 100644
index 0000000..415a8e4
--- /dev/null
+++ b/app/src/main/java/relax/offline/music/util/AnalysisUtil.kt
@@ -0,0 +1,9 @@
+package relax.offline.music.util
+
+import com.google.firebase.analytics.FirebaseAnalytics
+
+object AnalysisUtil {
+ private lateinit var firebaseAnalytics: FirebaseAnalytics
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/relax/offline/music/util/AppLifecycleHandler.kt b/app/src/main/java/relax/offline/music/util/AppLifecycleHandler.kt
new file mode 100644
index 0000000..883de0a
--- /dev/null
+++ b/app/src/main/java/relax/offline/music/util/AppLifecycleHandler.kt
@@ -0,0 +1,57 @@
+package relax.offline.music.util
+
+import android.app.Activity
+import android.app.Application
+import android.content.Intent
+import android.os.Bundle
+import android.os.SystemClock
+import relax.offline.music.App
+import relax.offline.music.activity.LaunchActivity
+
+/**
+ * 一个处理应用程序生命周期事件并管理启动页显示的类。
+ *
+ * @param application 应用程序实例。
+ */
+class AppLifecycleHandler(private val application: Application) : Application.ActivityLifecycleCallbacks {
+
+ private var activityReferences = 0
+ private var isActivityChangingConfigurations = false
+ private var lastPausedTime: Long = 0
+ private val intervalTime = 5000L
+
+ init {
+ application.registerActivityLifecycleCallbacks(this)
+ }
+
+ override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
+
+ override fun onActivityStarted(activity: Activity) {
+ if (++activityReferences == 1 && !isActivityChangingConfigurations) {
+ // 应用进入前台
+ val currentTime = SystemClock.elapsedRealtime()
+ val isAdShowing = App.app.isAdShowing.get()
+ //间隔时间是否满足,当前不是启动页,当前不是广告show
+ if (currentTime - lastPausedTime > intervalTime && activity !is LaunchActivity && !isAdShowing) {
+ val intent = Intent(activity, LaunchActivity::class.java)
+ activity.startActivity(intent)
+ }
+ }
+ }
+
+ override fun onActivityResumed(activity: Activity) {}
+
+ override fun onActivityPaused(activity: Activity) {}
+
+ override fun onActivityStopped(activity: Activity) {
+ isActivityChangingConfigurations = activity.isChangingConfigurations
+ if (--activityReferences == 0 && !isActivityChangingConfigurations) {
+ // 应用进入后台
+ lastPausedTime = SystemClock.elapsedRealtime()
+ }
+ }
+
+ override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
+
+ override fun onActivityDestroyed(activity: Activity) {}
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 3b28948..7edc5a0 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -3,4 +3,6 @@ plugins {
id("com.android.application") version "8.2.1" apply false
id("org.jetbrains.kotlin.android") version "1.9.22" apply false
id("org.jetbrains.kotlin.plugin.serialization") version "1.7.20" apply false
+ id("com.google.gms.google-services") version "4.3.15" apply false
+ id("com.google.firebase.crashlytics") version "2.9.5" apply false
}
\ No newline at end of file