fix(deeplink): 딥링크 포그라운드 라우팅을 정비한다
This commit is contained in:
@@ -10,6 +10,10 @@ import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Matrix
|
||||
@@ -18,6 +22,7 @@ import android.graphics.Path
|
||||
import android.graphics.Rect
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
@@ -51,6 +56,7 @@ import androidx.core.graphics.withTranslation
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.transform.CircleCropTransformation
|
||||
@@ -109,6 +115,8 @@ import kr.co.vividnext.sodalive.live.room.update.LiveRoomInfoEditDialog
|
||||
import kr.co.vividnext.sodalive.live.roulette.RoulettePreviewDialog
|
||||
import kr.co.vividnext.sodalive.live.roulette.RouletteSpinDialog
|
||||
import kr.co.vividnext.sodalive.live.roulette.config.RouletteConfigActivity
|
||||
import kr.co.vividnext.sodalive.main.DeepLinkActivity
|
||||
import kr.co.vividnext.sodalive.main.MainActivity
|
||||
import kr.co.vividnext.sodalive.report.ProfileReportDialog
|
||||
import kr.co.vividnext.sodalive.report.ReportType
|
||||
import kr.co.vividnext.sodalive.report.UserReportDialog
|
||||
@@ -116,6 +124,7 @@ import kr.co.vividnext.sodalive.settings.language.LanguageManager
|
||||
import kr.co.vividnext.sodalive.settings.notification.MemberRole
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.json.JSONObject
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.random.Random
|
||||
@@ -242,6 +251,22 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
}
|
||||
}
|
||||
|
||||
private val deepLinkConfirmReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val bundle = intent?.getBundleExtra(Constants.EXTRA_DATA) ?: return
|
||||
val destinationPageName = resolveDestinationPageName(bundle)
|
||||
|
||||
showDeepLinkNavigationDialog(destinationPageName) {
|
||||
val nextIntent = Intent(applicationContext, MainActivity::class.java).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
putExtra(Constants.EXTRA_DATA, bundle)
|
||||
}
|
||||
startActivity(nextIntent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
initAgora()
|
||||
@@ -265,6 +290,11 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
isForeground = true
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
deepLinkConfirmReceiver,
|
||||
IntentFilter(Constants.ACTION_LIVE_ROOM_DEEPLINK_CONFIRM)
|
||||
)
|
||||
|
||||
if (this::layoutManager.isInitialized) {
|
||||
layoutManager.scrollToPosition(chatAdapter.itemCount - 1)
|
||||
@@ -284,6 +314,12 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(deepLinkConfirmReceiver)
|
||||
isForeground = false
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
cropper.cleanup()
|
||||
hideKeyboard {
|
||||
@@ -297,6 +333,7 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
countDownTimer.cancel()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region setupView
|
||||
@@ -1177,7 +1214,7 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
val clickableSpan = object : ClickableSpan() {
|
||||
override fun onClick(widget: View) {
|
||||
val url = spannable.subSequence(start, end).toString()
|
||||
startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
|
||||
handleNoticeUrlClick(url)
|
||||
}
|
||||
}
|
||||
spannable.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
@@ -1187,6 +1224,135 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
private fun handleNoticeUrlClick(url: String) {
|
||||
val viewIntent = Intent(Intent.ACTION_VIEW, url.toUri())
|
||||
if (isInAppDeepLinkIntent(viewIntent)) {
|
||||
val deepLinkExtras = buildDeepLinkExtrasFromUri(viewIntent.data)
|
||||
val destinationPageName = resolveDestinationPageName(deepLinkExtras)
|
||||
|
||||
showDeepLinkNavigationDialog(destinationPageName) {
|
||||
startActivity(viewIntent)
|
||||
finish()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
startActivity(viewIntent)
|
||||
}
|
||||
|
||||
private fun isInAppDeepLinkIntent(intent: Intent): Boolean {
|
||||
val handlers = queryIntentActivitiesCompat(intent)
|
||||
return handlers.any { resolveInfo ->
|
||||
resolveInfo.activityInfo.packageName == packageName &&
|
||||
resolveInfo.activityInfo.name == DeepLinkActivity::class.java.name
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun queryIntentActivitiesCompat(intent: Intent): List<ResolveInfo> {
|
||||
val flags = PackageManager.MATCH_DEFAULT_ONLY
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
packageManager.queryIntentActivities(
|
||||
intent,
|
||||
PackageManager.ResolveInfoFlags.of(flags.toLong())
|
||||
)
|
||||
} else {
|
||||
packageManager.queryIntentActivities(intent, flags)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDeepLinkExtrasFromUri(data: Uri?): Bundle {
|
||||
val extras = Bundle()
|
||||
if (data == null) {
|
||||
return extras
|
||||
}
|
||||
|
||||
fun putQuery(key: String) {
|
||||
val value = data.getQueryParameter(key)
|
||||
if (!value.isNullOrBlank()) {
|
||||
extras.putString(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
putQuery("room_id")
|
||||
putQuery("channel_id")
|
||||
putQuery("message_id")
|
||||
putQuery("audition_id")
|
||||
putQuery("content_id")
|
||||
putQuery("deep_link_value")
|
||||
putQuery("deep_link_sub5")
|
||||
|
||||
val deepLinkValue = extras.getString("deep_link_value")
|
||||
val deepLinkValueId = extras.getString("deep_link_sub5")
|
||||
|
||||
if (!deepLinkValue.isNullOrBlank() && !deepLinkValueId.isNullOrBlank()) {
|
||||
when (deepLinkValue.lowercase(Locale.ROOT)) {
|
||||
"live" -> if (!extras.containsKey("room_id")) {
|
||||
extras.putString("room_id", deepLinkValueId)
|
||||
}
|
||||
|
||||
"channel" -> if (!extras.containsKey("channel_id")) {
|
||||
extras.putString("channel_id", deepLinkValueId)
|
||||
}
|
||||
|
||||
"content" -> if (!extras.containsKey("content_id")) {
|
||||
extras.putString("content_id", deepLinkValueId)
|
||||
}
|
||||
|
||||
"audition" -> if (!extras.containsKey("audition_id")) {
|
||||
extras.putString("audition_id", deepLinkValueId)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
return extras
|
||||
}
|
||||
|
||||
private fun resolveDestinationPageName(bundle: Bundle): String {
|
||||
val roomId = bundle.getString("room_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_ROOM_ID).takeIf { it > 0 }
|
||||
val channelId = bundle.getString("channel_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_USER_ID).takeIf { it > 0 }
|
||||
val messageId = bundle.getString("message_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_MESSAGE_ID).takeIf { it > 0 }
|
||||
val contentId = bundle.getString("content_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_AUDIO_CONTENT_ID).takeIf { it > 0 }
|
||||
|
||||
return when {
|
||||
roomId != null && roomId > 0 -> getString(R.string.screen_live_room_deeplink_target_live_room)
|
||||
channelId != null && channelId > 0 -> getString(R.string.screen_live_room_deeplink_target_channel_profile)
|
||||
contentId != null && contentId > 0 -> getString(R.string.screen_live_room_deeplink_target_content_detail)
|
||||
messageId != null && messageId > 0 -> getString(R.string.screen_live_room_deeplink_target_message)
|
||||
else -> {
|
||||
when (bundle.getString("deep_link_value")?.lowercase(Locale.ROOT)) {
|
||||
"live" -> getString(R.string.screen_live_room_deeplink_target_live_room)
|
||||
"channel" -> getString(R.string.screen_live_room_deeplink_target_channel_profile)
|
||||
"content" -> getString(R.string.screen_live_room_deeplink_target_content_detail)
|
||||
"series" -> getString(R.string.screen_live_room_deeplink_target_series_detail)
|
||||
"audition" -> getString(R.string.screen_live_room_deeplink_target_audition)
|
||||
else -> getString(R.string.screen_live_room_deeplink_target_default)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDeepLinkNavigationDialog(destinationPageName: String, onConfirm: () -> Unit) {
|
||||
SodaDialog(
|
||||
activity = this,
|
||||
layoutInflater = layoutInflater,
|
||||
title = getString(R.string.screen_live_room_deeplink_move_title),
|
||||
desc = getString(R.string.screen_live_room_deeplink_move_message, destinationPageName),
|
||||
confirmButtonTitle = getString(R.string.screen_live_room_yes),
|
||||
confirmButtonClick = {
|
||||
onConfirm()
|
||||
},
|
||||
cancelButtonTitle = getString(R.string.cancel),
|
||||
cancelButtonClick = {}
|
||||
).show(screenWidth)
|
||||
}
|
||||
|
||||
private fun onClickQuit() {
|
||||
hideKeyboard {
|
||||
if (viewModel.isEqualToHostId(SharedPreferenceManager.userId.toInt())) {
|
||||
@@ -3583,5 +3749,6 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
|
||||
|
||||
companion object {
|
||||
private const val NO_CHATTING_TIME = 180L
|
||||
var isForeground: Boolean = false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user