Firebase 추가

Crashlytics 추가
RemoteConfig 이용한 강제 업데이트 로직 추가
This commit is contained in:
2023-07-25 02:40:41 +09:00
parent edbaceba0b
commit fd8c4e726d
10 changed files with 380 additions and 8 deletions

View File

@@ -0,0 +1,74 @@
package kr.co.vividnext.sodalive.base
import android.app.Activity
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import kr.co.vividnext.sodalive.databinding.DialogSodaBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
open class SodaDialog(
activity: Activity,
layoutInflater: LayoutInflater,
title: String,
desc: String,
confirmButtonTitle: String,
confirmButtonClick: () -> Unit,
cancelButtonTitle: String = "",
cancelButtonClick: (() -> Unit)? = null,
) {
private val alertDialog: AlertDialog
val dialogView = DialogSodaBinding.inflate(layoutInflater)
init {
val dialogBuilder = AlertDialog.Builder(activity)
dialogBuilder.setView(dialogView.root)
alertDialog = dialogBuilder.create()
alertDialog.setCancelable(false)
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialogView.tvTitle.text = title
dialogView.tvDesc.text = desc
dialogView.tvCancel.text = cancelButtonTitle
dialogView.tvCancel.setOnClickListener {
alertDialog.dismiss()
cancelButtonClick?.let { it() }
}
dialogView.tvConfirm.text = confirmButtonTitle
dialogView.tvConfirm.setOnClickListener {
alertDialog.dismiss()
confirmButtonClick()
}
dialogView.tvCancel.visibility = if (cancelButtonTitle.isNotBlank()) {
View.VISIBLE
} else {
View.GONE
}
dialogView.tvConfirm.visibility = if (confirmButtonTitle.isNotBlank()) {
View.VISIBLE
} else {
View.GONE
}
}
fun show(width: Int) {
alertDialog.show()
val lp = WindowManager.LayoutParams()
lp.copyFrom(alertDialog.window?.attributes)
lp.width = width - (26.7f.dpToPx()).toInt()
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
alertDialog.window?.attributes = lp
}
}

View File

@@ -12,4 +12,8 @@ object Constants {
const val EXTRA_DATA = "extra_data"
const val EXTRA_TERMS = "extra_terms"
const val EXTRA_USER_ID = "extra_user_id"
const val EXTRA_ROOM_ID = "extra_room_id"
const val EXTRA_AUDIO_CONTENT_ID = "extra_audio_content_id"
}

View File

@@ -2,10 +2,21 @@ package kr.co.vividnext.sodalive.splash
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.core.os.bundleOf
import com.google.firebase.dynamiclinks.PendingDynamicLinkData
import com.google.firebase.dynamiclinks.ktx.dynamicLinks
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.ktx.get
import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import kr.co.vividnext.sodalive.BuildConfig
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.base.SodaDialog
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ActivitySplashBinding
import kr.co.vividnext.sodalive.main.MainActivity
@@ -15,21 +26,163 @@ import kr.co.vividnext.sodalive.user.login.LoginActivity
class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding::inflate) {
private val handler = Handler(Looper.getMainLooper())
private val remoteConfig = Firebase.remoteConfig
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (SharedPreferenceManager.token.isBlank()) {
showLoginActivity()
setupRemoteConfig()
fetchAndroidLatestVersion()
}
private fun setupRemoteConfig() {
val configSettings = remoteConfigSettings {
minimumFetchIntervalInSeconds = 300
}
remoteConfig.setConfigSettingsAsync(configSettings)
}
private fun fetchAndroidLatestVersion() {
remoteConfig.fetchAndActivate()
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
handler.post {
checkAppVersion(remoteConfig["android_latest_version"].asString())
}
} else {
checkFirebaseDynamicLink()
}
}
}
private fun checkAppVersion(latestVersion: String) {
val versions = BuildConfig.VERSION_NAME.split(".")
val latestVersions = latestVersion.split(".")
if (latestVersions.isNotEmpty() && latestVersions.size == versions.size) {
val latestMajor = latestVersions[0].toInt()
val latestMinor = latestVersions[1].toInt()
val latestPatch = latestVersions[2].toInt()
val major = versions[0].toInt()
val minor = versions[1].toInt()
val patch = versions[2].toInt()
if (latestMajor > major || (latestMajor == major && latestMinor > minor)) {
showUpdateDialog(isEssential = true)
} else if (latestMajor == major && latestMinor == minor && latestPatch > patch) {
showUpdateDialog(isEssential = false)
} else {
checkFirebaseDynamicLink()
}
} else {
showMainActivity()
checkFirebaseDynamicLink()
}
}
private fun showMainActivity() {
private fun showUpdateDialog(isEssential: Boolean = false) {
val desc = if (isEssential) {
"필수 업데이트가 있습니다.\n업데이트 후 사용가능합니다."
} else {
"최신 업데이트가 있습니다.\n업데이트 하시겠습니까?"
}
val cancelButtonClick = if (!isEssential) {
{ checkFirebaseDynamicLink() }
} else {
null
}
SodaDialog(
activity = this,
layoutInflater = layoutInflater,
title = "업데이트",
desc = desc,
confirmButtonTitle = "업데이트",
confirmButtonClick = {
startActivity(
Intent(
Intent.ACTION_VIEW,
Uri.parse("market://details?id=${BuildConfig.APPLICATION_ID}")
)
)
finish()
},
cancelButtonTitle = if (isEssential) {
""
} else {
"다음에"
},
cancelButtonClick = cancelButtonClick
).show(screenWidth)
}
private fun checkFirebaseDynamicLink() {
Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener(this) { getDynamicLinkSuccess(it) }
.addOnFailureListener(this) { getDynamicLinkFailure() }
}
private fun getDynamicLinkSuccess(pendingDynamicLinkData: PendingDynamicLinkData?) {
var deepLink: Uri? = null
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.link
}
val extras = if (deepLink != null) {
val roomIdString = deepLink.getQueryParameter("room_id")
val channelIdString = deepLink.getQueryParameter("channel_id")
val audioContentIdString = deepLink.getQueryParameter("audio_content_id")
if (roomIdString != null) {
bundleOf(
Constants.EXTRA_ROOM_ID to roomIdString.toLong()
)
} else if (channelIdString != null) {
bundleOf(
Constants.EXTRA_USER_ID to channelIdString.toLong()
)
} else if (audioContentIdString != null) {
bundleOf(
Constants.EXTRA_AUDIO_CONTENT_ID to audioContentIdString.toLong()
)
} else {
null
}
} else if (intent.extras != null) {
intent.extras
} else {
null
}
startNextActivity(extras = extras)
}
private fun getDynamicLinkFailure() {
val extras = intent.getBundleExtra(Constants.EXTRA_DATA)
?: if (intent.extras != null) {
intent.extras
} else {
null
}
startNextActivity(extras = extras)
}
private fun startNextActivity(extras: Bundle? = null) {
if (SharedPreferenceManager.token.isBlank()) {
showLoginActivity(extras)
} else {
showMainActivity(extras)
}
}
private fun showMainActivity(extras: Bundle?) {
handler.postDelayed({
startActivity(
Intent(applicationContext, MainActivity::class.java).apply {
putExtra(Constants.EXTRA_DATA, extras)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
@@ -38,10 +191,11 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
}, 500)
}
private fun showLoginActivity() {
private fun showLoginActivity(extras: Bundle?) {
handler.postDelayed({
startActivity(
Intent(applicationContext, LoginActivity::class.java).apply {
putExtra(Constants.EXTRA_DATA, extras)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}