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

Lea*_*mpo 10 android android-jetpack android-architecture-navigation android-jetpack-navigation

这次我需要你的帮助来使用带有深度链接的 android 导航组件。

我一直在关注这个文档,片段和深层链接之间的连接工作正常。

问题在于接收深层链接的活动。就我而言,我设置了 android:launchMode="singleTask"

<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)
}
Run Code Online (Sandbox Code Playgroud)

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

每次单击深层链接时,WelcomeActivity 都会收到两次 onNewIntent 调用。甚至有时会创建该活动的新实例..就像

1_ object1-onNewIntent

2_ object1-onNewIntent

3_ object2-onCreate

这里有一些日志:

首次发布

onCreate:意图 { 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

onCreate: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://{depp_link}... flg=0x1001c000 cmp={applicationId}/{package}.WelcomeActivity (有额外的)} 与活动:{package}.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.BROWSABLE] dat=https://{depp_link}... flg=0x1001c000 cmp={applicationId}/{package}.WelcomeActivity (有额外的)} 与活动:{package}.WelcomeActivity@b78f4df

onCreate: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://{depp_link}... flg=0x1001c000 cmp={applicationId}/{package}.WelcomeActivity (有额外的)} 与 {package}.WelcomeActivity@dfe87b2

更新:

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

2- navController.navigate(intent.dataString.toUri()) 似乎工作正常。所以我猜问题是 navController.handleDeepLink(intent)。

Lea*_*mpo 11

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

这是我尝试过的:

我从导航中删除了 deepLink,并且深层链接工作得很好(我已手动添加了 deepLink),具有正常行为:使用 singleTask,如果活动已创建,则 onNewIntent 仅被调用一次。如果活动未创建,则调用 onCreate。

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

我决定尝试从 NavController 中尝试“navigate(Uri deepLink)”,我发现它正在按预期工作(第一段中描述的行为)。有了这个替代方法,我决定做一些改变:

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)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

请务必注意 onCreate 中的这段代码:

val data = intent.data
intent.data = null
Run Code Online (Sandbox Code Playgroud)

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

navController.graph.hasDeepLink(uri) 将帮助您查看您的图表是否可以处理该 uri。如果不使用它,那么“navigate(Uri deepLink)”将抛出异常。

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


A. *_*rov 6

当回调onNewIntent第一次到达时,只需设置标志intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);并将突变的意图传递给handleDeepLink(intent);

此标志消除了第二到达的onNewIntent因重新连接到现有的回调Activity(与堆栈中微量的全面重建所需深层链接目标),而不是推出新的Activity

详细信息在handleDeepLink方法的源代码中。

  • 这很好用。然而,它在 API 19 上给了我奇怪的行为,深度链接之前的片段也被删除了。`intent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 或 Intent.FLAG_ACTIVITY_CLEAR_TASK)` 解决了我的问题。 (3认同)