当前位置: 首页 > 知识库问答 >
问题:

具有深度链接的Android导航组件:onNewIntent多次调用

邹杰
2023-03-14

这一次,我需要你的帮助关于使用Android导航组件与深度链接。

我一直在关注这个文档,fragment和deeplink之间的连接工作正常。

这个问题是关于接收深度链接的活动的。在我的例子中,我设置了android: LaunchMode="单项任务"

<activity android:name=".features.welcome.WelcomeActivity"
    android:launchMode="singleTask">
     <nav-graph android:value="@navigation/welcome_nav_graph" />
</activity>

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    Timber.d("onNewIntent: $intent with activity: $this")
    navController.handleDeepLink(intent)
}

通过这种配置,我注意到了一些奇怪的行为:

WelcomeActivity每次单击deeplink都会收到两次onNewIntent呼叫。有时甚至会创建新的活动实例。。喜欢

1_uu对象1 onNewIntent

2_uu对象1 onNewIntent

3_uu2onCreate

这里有一些日志:

首次发射

onCreate:Intent{flg=0x10000000 cmp={applicationId}/{package}。WelcomeActivity}与活动:{package}。WelcomeActivity@4adbef0

开放深度链接

onNewIntent:Intent{act=android.Intent.action.VIEW cat=[android.Intent.category.BROWSABLE]dat=https://{depp_link}…flg=0x10010000 cmp={applicationId}/{package}。WelcomeActivity(有额外功能)}与活动:{package}。WelcomeActivity@4adbef0

onNewIntent:Intent{act=android.Intent.action.VIEW cat=[android.Intent.category.BROWSABLE]dat=https://{depp_link}。。。flg=0x1001c000 cmp={applicationId}/{package}。WelcomeActivity(有额外功能)}与活动:{package}。WelcomeActivity@4adbef0

在创建:意图{act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE]dat=https://{depp_link}... flg=0x1001c000 cmp={应用ID}/{包}。欢迎活动(有额外功能)}带活动:{包}.WelcomeActivity@b77c6b

关闭应用程序并打开深层链接

onCreate:Intent{act=android.Intent.action.VIEW cat=[android.Intent.category.BROWSABLE]dat=https://{depp_link}。。。flg=0x10018000 cmp={applicationId}/{package}。WelcomeActivity(有额外功能)}与活动:{package}。WelcomeActivity@b78f4df

onNewIntent: Intent{act=android.intent.action.VIEW cat=[android.intent.category.浏览]dat=https://{depp_link}... flg=0x1001c000 cmp={应用ID}/{包}。欢迎活动(有额外功能)}带活动:{包}.WelcomeActivity@b78f4df

在创建:意图{act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE]dat=https://{depp_link}... flg=0x1001c000 cmp={应用程序id}/{包}。欢迎活动(有额外功能)}带{包}.WelcomeActivity@dfe87b2

更新:

1-似乎启动模式与此问题无关。我注意到默认启动模式也是如此。

2-导航控制器。导航(intent.dataString.toUri())似乎工作正常。所以我想问题在于导航控制器。handleDeepLink(意图)。

共有3个答案

田骁
2023-03-14
匿名用户

当一个隐式的深层链接被点击时,FLAG_ACTIVITY_NEW_TASK被有意地设置。并且根据留档,后栈将被重新创建到一个良好的状态。请参见这里的留档隐式深层链接。

如果您不想要这种行为,也不想更改意图标志,您可以自己处理深度链接,而不是将其传递给导航组件。因此,如果您使用的是AdvancedNavigationSample,您需要删除handle深度链接,并使用findNavController()。导航()指向方向。

另外,请记住,将启动器活动的启动模式设置为Single任务,以便在单击深度链接或通知时接收新意图。

  1. 更换导航控制器。handledeeplink()在带有
fun BottomNavigationView.navigateDeeplink(
    navGraphIds: List<Int>,
    fragmentManager: FragmentManager,
    containerId: Int,
    uri: Uri
) {
    navGraphIds.forEachIndexed { index, navGraphId ->
        val fragmentTag = getFragmentTag(index)

        // Find or create the Navigation host fragment
        val navHostFragment = obtainNavHostFragment(
            fragmentManager,
            fragmentTag,
            navGraphId,
            containerId
        )
        // Handle deeplink
        val canHandleDeeplink = navHostFragment.navController.graph.hasDeepLink(uri)

        if (canHandleDeeplink) {
            if (selectedItemId != navHostFragment.navController.graph.id) {
                selectedItemId = navHostFragment.navController.graph.id
            }
            navHostFragment.lifecycleScope.launchWhenResumed {
                // Wait for fragment to restore state from backStack
                // otherwise navigate will be ignored
                // Ignoring navigate() call: FragmentManager has already saved its state
                navHostFragment.navController.navigateOnce(uri)
            }
        }
    }
}

完整的解决方案在此示例中实现。

优点:

  1. 您可以用同样的方法直接处理通知点击。从动作中创建一个深度链接,并将其传递到intent中。数据在PendingEvent中
  2. 您可以根据需要验证和更改deeplink。如用户未登录,则直接进入登录活动或移动到指定目的地

傅嘉悦
2023-03-14

当onNewIntent上的callback第一次到达时,只需设置标志intent即可。添加标志(意图、标志、活动、清除任务) 并将突变的意图传递给handleDeepLink(意图)

由于重新连接到现有的活动(将backbackback trace完全重建到所需的深度链接目的地),而不是启动新的活动,此标志消除了第二次到达的onNewIntent回调。

详细信息请参见handleDeepLink方法的源代码。

景辰钊
2023-03-14

通过测试不同的变化,我得出结论,“navController.handleDeepLink(intent)”导致了这种奇怪的行为。

这就是我尝试的:

我从导航中删除了深层链接,深层链接工作得很好(我手动添加了深层链接),行为很正常:使用单一任务,如果活动已经创建,那么onNewIntent只被调用一次。如果活动没有创建,那么onCreate被调用。

另外一个问题是,navController.handleDeepLink(意图)将在onCreate中自动调用(您可以在javadocs中检查)。当调用onNewIntent时,您需要调用navController.handleDeepLink(意图)。

我决定尝试NavController的“导航(Uri深度链接)”,我看到这是按预期工作的(第一段中描述的行为)。有了这个替代方法,我决定做一些改变:

class WelcomeActivity : AppCompatActivity(){

      private val navController by lazy { findNavController(R.id.nav_host_fragment) }

      private var deepLinkData: Uri? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Timber.d("onCreate: $intent  with activity: $this")
        val data = intent.data
        intent.data = null
        setContentView(R.layout.activity_welcome)
        handleDeepLink(data)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        Timber.d("onNewIntent: $intent with activity: $this")
        setIntent(intent)
        val data = intent?.data
        handleDeepLink(data)
    }

    private fun handleDeepLink(uri: Uri?) {
        //TODO: there is an issue that will cause onNewIntent to be called twice when the activity is already present.
        if (uri != null && deepLinkData.toString() != uri.toString() && navController.graph.hasDeepLink(uri)) {
            //possible deep link for LoginFragment
            deepLinkData = uri
            navController.navigate(uri)
        }
    }

}

重要的是要注意在onCreate中的这段代码:

val data = intent.data
intent.data = null

这样做的原因是,如果我需要阻止调用“navController.handleDeepLink(intent)”,因为如果存在该信息,就会自动调用它,从而导致奇怪的行为。

导航控制器。图表hasDeepLink(uri)将帮助您查看图形是否可以处理该uri。如果不使用它,则“导航(Uri deepLink)”将引发异常。

如果你遇到同样的问题,希望它能帮助你。如果你对此有更多的见解,请随时发表评论。

 类似资料:
  • 当我从deeplink(用户点击URL)打开应用程序并按下后退按钮时,我希望用户导航到我导航图中的前一个片段,但它只是退出应用程序。 文件中说,反向导航的工作方式应该与用户自然到达屏幕的方式相同。 我可以在导航图中指定所需的backbackback吗?或者可以在deeplink后自动形成Backback?对于旧版本的库,我发现在按back press键后,它应该导航到导航图的根目录,但事实并非如此

  • 如果我打开在桌面浏览器上收到的电子邮件中的链接,则用户的电子邮件被成功验证(标志FirebaseUser.isemailVerificed返回true) 然而,我尝试使用深度链接。因此,如果用户点击移动设备上的链接,将在应用程序中重定向,我有深度链接监听器。我希望当我收到应用程序内的深度链接数据时,isemailverificed标志会立即更新,但事实并非如此)。实际上,即使在按下链接时,也应该进

  • TL;DR:与Spotify iPad应用程序类似的具有深度导航功能的多窗格应用程序应该如何在Android上看起来和工作,以及如何实现这一点? 在模型中,用户看到一个初始概览,然后从第一个列表中选择“项目#2”。一个新的活动开始了,向他展示了项目2的详细信息。在这里,他选择查看与项目#2相关的事物的列表。第三张图片中的新openend活动显示了这个列表,点击其中一个就会打开这个东西的详细信息。他

  • 我正在一个新的Android应用程序上使用导航组件,但我不知道怎么做 首先,我有我的主活动,我有main_navigation_graph 主要活动 NavHostFragment main_navigation_graph里面有3个碎片 这里一切都很好。问题是当我到达最后一个片段时,因为在这个片段上,我想根据BottomNavigationView输入(暂时)显示一些子片段(在新的NavHost

  • 我正在实现Android深度链接的概念,它工作正常,我的问题是,如果应用程序没有安装在手机上,我想将链接重定向到我的play store应用程序页面。 请引导我找到它,谢谢。

  • viewmodel随活动或其所连接的片段而生或死。这产生了某些后果,我无法理解为什么没有人询问(如果我们将导航架构融入图片中)。 根据最新的android博客和导航框架的工作方式,建议我们进入单活动多片段诗句。 假设我有以下应用程序设计。 现在,由于我使用共享视图模型,这意味着我的视图模型将附加到活动。然而,这似乎是泄漏的。就像如果我从A到E一路遍历,现在回来弹出片段到片段B,视图模型CDE应该被