Distinguish developer and publisher deep links

The deep-link router matched "/apps/dev" as a substring, so publisher
links (/store/apps/developer?id=<name>) were treated as developer-stream
links and failed to resolve. Match the exact action keyword (last path
segment, or host for market:// links) instead, and add a
Screen.PublisherProfile that renders the publisher-search overload of
DevProfileScreen.

Both /dev and /developer links may carry either a numeric developer id
(curated developer stream) or a developer name (publisher search), so
the id is parsed to long to decide which screen to open.

Also drop the now-dead ACTION_VIEW branch from ComposeActivity, since
DeepLinkConfirmActivity owns all external VIEW deep links.
This commit is contained in:
Rahul Patel
2026-05-31 02:09:21 +05:30
parent e1b8b5ae95
commit ce04b859fd
4 changed files with 25 additions and 20 deletions

View File

@@ -6,7 +6,6 @@
package com.aurora.store
import android.content.Intent
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.compose.setContent
@@ -152,22 +151,11 @@ class ComposeActivity : FragmentActivity() {
}
private fun resolveStartDestination(): Screen {
// Parcel-based navigation (e.g. from NotificationUtil or DeepLinkConfirmActivity)
// Parcel-based navigation (e.g. from NotificationUtil or DeepLinkConfirmActivity, which
// owns the external ACTION_VIEW market:// and play.google.com deep links)
IntentCompat.getParcelableExtra(intent, Screen.PARCEL_KEY, Screen::class.java)
?.let { return it }
// Deep links via ACTION_VIEW
if (intent.action == Intent.ACTION_VIEW) {
val data = intent.data
val path = data?.path.orEmpty()
val id = data?.getQueryParameter("id")
return when {
id != null && path.contains("/apps/dev") -> Screen.DevProfile(id)
id != null -> Screen.AppDetails(id)
else -> defaultStart()
}
}
// SEND / SHOW_APP_INFO — getPackageName() handles both
intent.getPackageName()?.let { return Screen.AppDetails(it) }

View File

@@ -52,16 +52,22 @@ class DeepLinkConfirmActivity : FragmentActivity() {
/**
* Resolves the listing requested by the incoming ACTION_VIEW intent, or null when the intent
* carries no app/developer id.
* carries no id. The action keyword ("details", "dev" or "developer") is the last path segment
* for play.google.com links and the host for market:// links. Both "dev" and "developer" links
* may carry either a numeric developer id (curated developer stream) or a developer name
* (publisher search), so the id is parsed to decide which one to open.
*/
private fun resolveDeepLink(): Screen? {
if (intent.action != Intent.ACTION_VIEW) return null
val data = intent.data
val path = data?.path.orEmpty()
val id = data?.getQueryParameter("id") ?: return null
return when {
path.contains("/apps/dev") -> Screen.DevProfile(id)
val data = intent.data ?: return null
val id = data.getQueryParameter("id") ?: return null
return when (data.lastPathSegment ?: data.host) {
"dev", "developer" -> when {
id.toLongOrNull() != null -> Screen.DevProfile(id)
else -> Screen.PublisherProfile(id)
}
else -> Screen.AppDetails(id)
}
}
@@ -100,6 +106,7 @@ class DeepLinkConfirmActivity : FragmentActivity() {
private fun Screen.deepLinkLabel(): String = when (this) {
is Screen.AppDetails -> packageName
is Screen.DevProfile -> developerId
is Screen.PublisherProfile -> publisherId
else -> ""
}
}

View File

@@ -216,6 +216,13 @@ fun NavDisplay(startDestination: NavKey) {
)
}
entry<Screen.PublisherProfile> { screen ->
DevProfileScreen(
publisherId = screen.publisherId,
onNavigateTo = ::navigate
)
}
entry<Screen.PermissionRationale> { screen ->
PermissionRationaleScreen(
requiredPermissions = screen.requiredPermissions

View File

@@ -29,6 +29,9 @@ sealed class Screen : NavKey, Parcelable {
@Serializable
data class DevProfile(val developerId: String) : Screen()
@Serializable
data class PublisherProfile(val publisherId: String) : Screen()
@Serializable
data class AppDetails(val packageName: String) : Screen()