fix(deeplink): 푸시 딥링크 우선 분기로 혼합 라우팅을 방지한다

This commit is contained in:
2026-03-13 11:34:16 +09:00
parent 3287421614
commit 0f371ffd0e
4 changed files with 344 additions and 8 deletions

View File

@@ -75,14 +75,20 @@ class SodaFirebaseMessagingService : FirebaseMessagingService() {
}
}
val deepLinkExtras = android.os.Bundle().apply {
messageData["room_id"]?.let { putString("room_id", it) }
messageData["message_id"]?.let { putString("message_id", it) }
messageData["content_id"]?.let { putString("content_id", it) }
messageData["channel_id"]?.let { putString("channel_id", it) }
messageData["audition_id"]?.let { putString("audition_id", it) }
messageData["deep_link_value"]?.let { putString("deep_link_value", it) }
messageData["deep_link_sub5"]?.let { putString("deep_link_sub5", it) }
val deepLinkExtras = if (!deepLinkUrl.isNullOrBlank()) {
android.os.Bundle().apply {
putString("deep_link", deepLinkUrl)
}
} else {
android.os.Bundle().apply {
messageData["room_id"]?.let { putString("room_id", it) }
messageData["message_id"]?.let { putString("message_id", it) }
messageData["content_id"]?.let { putString("content_id", it) }
messageData["channel_id"]?.let { putString("channel_id", it) }
messageData["audition_id"]?.let { putString("audition_id", it) }
messageData["deep_link_value"]?.let { putString("deep_link_value", it) }
messageData["deep_link_sub5"]?.let { putString("deep_link_sub5", it) }
}
}
if (!deepLinkExtras.isEmpty) {

View File

@@ -5,9 +5,15 @@ import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
import kr.co.vividnext.sodalive.app.SodaLiveApp
import kr.co.vividnext.sodalive.audition.AuditionActivity
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCommunityAllActivity
import kr.co.vividnext.sodalive.live.room.LiveRoomActivity
import kr.co.vividnext.sodalive.message.MessageActivity
import kr.co.vividnext.sodalive.mypage.can.payment.CanPaymentActivity
import kr.co.vividnext.sodalive.splash.SplashActivity
import java.util.Locale
@@ -18,6 +24,7 @@ class DeepLinkActivity : AppCompatActivity() {
val data: Uri? = intent?.data
val deepLinkExtras = buildDeepLinkExtras(intent)
val deepLinkUrl = deepLinkExtras?.getString("deep_link")
if (data != null && data.scheme != null) {
val host = data.host
@@ -46,6 +53,15 @@ class DeepLinkActivity : AppCompatActivity() {
}
if (SodaLiveApp.isAppInForeground) {
if (!deepLinkUrl.isNullOrBlank()) {
deepLinkExtras?.let {
if (routeForegroundDeepLink(it)) {
finish()
return
}
}
}
startActivity(
Intent(applicationContext, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
@@ -70,6 +86,10 @@ class DeepLinkActivity : AppCompatActivity() {
val data = intent.data
data?.toString()?.takeIf { it.isNotBlank() }?.let {
extras.putString("deep_link", it)
}
fun putIfAbsent(key: String, value: String?) {
if (!value.isNullOrBlank() && !extras.containsKey(key)) {
extras.putString(key, value)
@@ -106,6 +126,7 @@ class DeepLinkActivity : AppCompatActivity() {
copyString("message_id")
copyString("audition_id")
copyString("content_id")
copyString("deep_link")
copyString("deep_link_value")
copyString("deep_link_sub5")
@@ -142,6 +163,14 @@ class DeepLinkActivity : AppCompatActivity() {
extras.putString("content_id", it.toString())
}
intent.getStringExtra("deep_link")?.takeIf { it.isNotBlank() }?.let {
extras.putString("deep_link", it)
}
intent.getStringExtra("deepLink")?.takeIf { it.isNotBlank() }?.let {
extras.putString("deep_link", it)
}
if (data != null) {
applyPathDeepLink(data = data, putIfAbsent = ::putIfAbsent)
}
@@ -186,6 +215,158 @@ class DeepLinkActivity : AppCompatActivity() {
}
}
private fun routeForegroundDeepLink(bundle: Bundle): Boolean {
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 }
val auditionId = bundle.getString("audition_id")?.toLongOrNull()
?: bundle.getLong(Constants.EXTRA_AUDITION_ID).takeIf { it > 0 }
val communityCreatorId = bundle.getString(Constants.EXTRA_COMMUNITY_CREATOR_ID)?.toLongOrNull()
?: bundle.getLong(Constants.EXTRA_COMMUNITY_CREATOR_ID).takeIf { it > 0 }
when {
roomId != null && roomId > 0 -> {
startActivity(
Intent(applicationContext, LiveRoomActivity::class.java).apply {
putExtra(Constants.EXTRA_ROOM_ID, roomId)
}
)
return true
}
channelId != null && channelId > 0 -> {
startActivity(
Intent(applicationContext, UserProfileActivity::class.java).apply {
putExtra(Constants.EXTRA_USER_ID, channelId)
}
)
return true
}
contentId != null && contentId > 0 -> {
startActivity(
Intent(applicationContext, AudioContentDetailActivity::class.java).apply {
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, contentId)
}
)
return true
}
messageId != null && messageId > 0 -> {
startActivity(Intent(applicationContext, MessageActivity::class.java))
return true
}
communityCreatorId != null && communityCreatorId > 0 -> {
startActivity(
Intent(applicationContext, CreatorCommunityAllActivity::class.java).apply {
putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, communityCreatorId)
}
)
return true
}
auditionId != null && auditionId > 0 -> {
startActivity(Intent(applicationContext, AuditionActivity::class.java))
return true
}
}
val deepLinkValue = bundle.getString("deep_link_value")
val deepLinkValueId = bundle.getString("deep_link_sub5")?.toLongOrNull()
return routeByDeepLinkValue(deepLinkValue = deepLinkValue, deepLinkValueId = deepLinkValueId)
}
private fun routeByDeepLinkValue(deepLinkValue: String?, deepLinkValueId: Long?): Boolean {
if (deepLinkValue.isNullOrBlank()) {
return false
}
return when (deepLinkValue.lowercase(Locale.ROOT)) {
"series" -> {
if (deepLinkValueId == null || deepLinkValueId <= 0) {
return false
}
startActivity(
Intent(applicationContext, SeriesDetailActivity::class.java).apply {
putExtra(Constants.EXTRA_SERIES_ID, deepLinkValueId)
}
)
true
}
"content" -> {
if (deepLinkValueId == null || deepLinkValueId <= 0) {
return false
}
startActivity(
Intent(applicationContext, AudioContentDetailActivity::class.java).apply {
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, deepLinkValueId)
}
)
true
}
"channel" -> {
if (deepLinkValueId == null || deepLinkValueId <= 0) {
return false
}
startActivity(
Intent(applicationContext, UserProfileActivity::class.java).apply {
putExtra(Constants.EXTRA_USER_ID, deepLinkValueId)
}
)
true
}
"live" -> {
if (deepLinkValueId == null || deepLinkValueId <= 0) {
return false
}
startActivity(
Intent(applicationContext, LiveRoomActivity::class.java).apply {
putExtra(Constants.EXTRA_ROOM_ID, deepLinkValueId)
}
)
true
}
"community" -> {
if (deepLinkValueId == null || deepLinkValueId <= 0) {
return false
}
startActivity(
Intent(applicationContext, CreatorCommunityAllActivity::class.java).apply {
putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, deepLinkValueId)
}
)
true
}
"message" -> {
startActivity(Intent(applicationContext, MessageActivity::class.java))
true
}
"audition" -> {
startActivity(Intent(applicationContext, AuditionActivity::class.java))
true
}
else -> false
}
}
private fun applyPathDeepLink(
data: Uri,
putIfAbsent: (key: String, value: String?) -> Unit

View File

@@ -8,6 +8,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.ColorStateList
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
@@ -60,6 +61,7 @@ import java.util.Locale
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import androidx.core.net.toUri
@UnstableApi
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
@@ -312,6 +314,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
}
private fun executeBundleDeeplink(bundle: Bundle): Boolean {
val deepLinkUrl = bundle.getString("deep_link")
if (!deepLinkUrl.isNullOrBlank()) {
val deepLinkBundle = buildBundleFromDeepLinkUrl(deepLinkUrl)
if (deepLinkBundle != null) {
return executeBundleRoute(deepLinkBundle)
}
return false
}
return executeBundleRoute(bundle)
}
private fun executeBundleRoute(bundle: Bundle): Boolean {
val roomId = bundle.getString("room_id")?.toLongOrNull()
?: bundle.getLong(Constants.EXTRA_ROOM_ID).takeIf { it > 0 }
val channelId = bundle.getString("channel_id")?.toLongOrNull()
@@ -385,6 +401,95 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
return false
}
private fun buildBundleFromDeepLinkUrl(deepLinkUrl: String): Bundle? {
val data = runCatching { deepLinkUrl.toUri() }.getOrNull() ?: return null
val extras = Bundle().apply {
putString("deep_link", deepLinkUrl)
}
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")
putQuery(Constants.EXTRA_COMMUNITY_CREATOR_ID)
applyPathDeepLink(data = data) { key, value ->
if (!value.isNullOrBlank() && !extras.containsKey(key)) {
extras.putString(key, value)
}
}
return extras
}
private fun applyPathDeepLink(
data: Uri,
putIfAbsent: (key: String, value: String?) -> Unit
) {
val host = data.host?.lowercase(Locale.ROOT).orEmpty()
val pathSegments = data.pathSegments.filter { it.isNotBlank() }
val pathType: String
val pathId: String?
if (host.isNotBlank() && host != "payverse") {
pathType = host
pathId = pathSegments.firstOrNull()
} else if (pathSegments.isNotEmpty()) {
pathType = pathSegments[0].lowercase(Locale.ROOT)
pathId = pathSegments.getOrNull(1)
} else {
return
}
when (pathType) {
"live" -> {
putIfAbsent("room_id", pathId)
putIfAbsent("deep_link_value", "live")
putIfAbsent("deep_link_sub5", pathId)
}
"content" -> {
putIfAbsent("content_id", pathId)
putIfAbsent("deep_link_value", "content")
putIfAbsent("deep_link_sub5", pathId)
}
"series" -> {
putIfAbsent("deep_link_value", "series")
putIfAbsent("deep_link_sub5", pathId)
}
"community" -> {
putIfAbsent("deep_link_value", "community")
putIfAbsent(Constants.EXTRA_COMMUNITY_CREATOR_ID, pathId)
putIfAbsent("deep_link_sub5", pathId)
}
"message" -> {
putIfAbsent("deep_link_value", "message")
putIfAbsent("message_id", pathId)
putIfAbsent("deep_link_sub5", pathId)
}
"audition" -> {
putIfAbsent("deep_link_value", "audition")
putIfAbsent("audition_id", pathId)
putIfAbsent("deep_link_sub5", pathId)
}
}
}
private fun executeOneLink() {
val deepLinkValue = SharedPreferenceManager.marketingLinkValue
val deepLinkValueId = SharedPreferenceManager.marketingLinkValueId