android Jetpack Compose中的深度链接处理

5kgi1eie  于 2023-05-21  发布在  Android
关注(0)|答案(1)|浏览(210)

我正在开发一个商店应用程序。用户可以通过消息、电子邮件等方式分享产品。我的任务是一旦收到共享链接的Oter用户点击该链接,我的应用程序应该打开并导航到产品详细信息页面,并使用URI中的产品ID来获取产品。
我使用Firebase动态链接来生成短链接。当我点击链接让说在消息应用程序.我的应用程序将在消息应用程序中打开,而不是作为单独的应用程序打开。我通过将活动启动模式更改为

android:launchMode="singleTask"

只有当我的应用程序没有启动时它才能工作。但是当应用程序在后台时,点击链接不会做任何事情。
我不确定如何在NewIntent(intent:Intent?)函数来正确处理深度链接。目前,我发现TEMP解决方案是工作,但我不知道如果它的正确的方式这样做。我的newIntent代码。

class MainActivity : ComponentActivity() {
    
    override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    
    val pendingIntent = TaskStackBuilder.create(applicationContext).run {
    addNextIntentWithParentStack(intent)
    getPendingIntent(
    0,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )
            }
    pendingIntent.send()
        }
     }

我的清单文件:

<activity android:launchMode="singleTask" android:name=".presentation.MainActivity" android:exported="true" android:theme="@style/Theme.B2CApp">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="https" />
                <data android:host="*****.page.link" />
            </intent-filter>
        </activity>

这就是我如何使用deepLink导航

composable(
                    CategoryRoute.ProductDetail.route,
                    deepLinks = listOf(
                        navDeepLink {
                            uriPattern = "****.page.link/{$DEEP_LINK}"
                            action = Intent.ACTION_VIEW
                        }
                    ),
                    arguments = listOf(
                        navArgument(PRODUCT_ID) {
                            type = NavType.StringType
                            defaultValue = ""
                        },
                        navArgument(DEEP_LINK) {
                            type = NavType.StringType
                            defaultValue = ""
                        }
                    )
                )

我试图调用havController来处理newIntent func中的深层链接,但我无法访问MainActivity文件中的navHostController。
更新:@Watermelon建议之后:我的清单文件没有更改。我的主要活动现在看起来像这样:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val newIntent by produceState(initialValue = null as Intent?) {
                val consumer = androidx.core.util.Consumer<Intent> {
                    this.value = it
                }
                addOnNewIntentListener(consumer)
                awaitDispose {
                    removeOnNewIntentListener(consumer)
                }
            }
            B2CTheme {
                MainScreen(newIntent)
            }
        }
    }
}

我的主屏幕是:

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(newIntent: Intent?) {
    val navController = rememberNavController()
    val systemUiController = rememberSystemUiController()
    val currentIntent = rememberUpdatedState(newValue = newIntent)

    LaunchedEffect(Unit) {
        snapshotFlow { currentIntent.value }.filterNotNull()
            .map {
                /* do extra jobs*/
                println(it.dataString)
                it

            }
            .collect{
                navController.handleDeepLink(it)
            }
    }

    SideEffect {
        systemUiController.setStatusBarColor(
            color = LightColorScheme.surface,
            darkIcons = true
        )
    }

    Scaffold(
        bottomBar = {
            B2CBottomBar(navController) {
                navController.navigate(it.route) {
                    launchSingleTop = true
                    popUpTo(it.route) {
                        inclusive = true
                    }
                }
            }
        }
    ) {
        MainNavHost(
            navController = navController,
            Modifier.padding(top = it.calculateTopPadding()))
    }
}

另外,我最初的解决方案有一个bug。当用户从外部单击链接时,我的应用程序会打开并在我的HomeTab中正确显示产品。如果我点击后退按钮,它会带我回到根主页选项卡。如果我从底部导航中选择任何其他选项卡并再次单击Home选项卡,我仍然可以看到从DeepLink获得的产品。

xdyibdwo

xdyibdwo1#

1.如果您可以直接访问活动。

val navController = rememberNavController()
    DisposableEffect(navController) {
        val consumer = Consumer<Intent> {
            navController.handleDeepLink(it)
        }
        this@MainActivity.addOnNewIntentListener(consumer)
        onDispose {
            this@MainActivity.removeOnNewIntentListener(consumer)
        }
    }

2.或者如果你想解耦它的一些方式。

class FeatureHostingActivity: ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val newIntent by produceState(initialValue = null as Intent?) {
                val consumer = androidx.core.util.Consumer<Intent> {
                    this.value = it
                }
                addOnNewIntentListener(consumer)
                awaitDispose {
                    removeOnNewIntentListener(consumer)
                }
            }
            FeatureApp(newIntent)
        }
    }

}

FeatureApp可以像这样处理Intent

@Composable
fun FeatureApp(newIntent:Intent?) {
    
    val currentIntent = rememberUpdatedState(newValue = newIntent)
    val navController = rememberNavController()
    LaunchedEffect(Unit) {
        snapshotFlow { currentIntent.value }.filterNotNull()
            .map { 
                /* do extra jobs*/
                it
            }
            .collect{
                navController.handleDeepLink(it)
        }
    }
    /* your features */
}

如果handleDeepLink没有像你预期的那样工作,考虑在你的intent过滤器中添加IntentFlags。

  • FLAG_ACTIVITY_SINGLE_TOP
  • 标记活动清除任务
  • FLAG_ACTIVITY_CLEAR_TOP
  • 标记_活动_新任务

或者配置它并通过调用navigate而不是handleDeepLink自行导航到目的地。但是我不推荐这种方式,因为这会导致通过deeplink启动新活动与使用deeplink更新现有活动之间的不同行为

相关问题