Android 隐式深层链接:Intent 中的额外内容为空
Android implicit deeplinking: null extras in Intent
我想使用导航组件创建隐式深层链接。
但是当我使用以下 URL:
启动我的应用程序时
https://my-app.com/cars/ef123-aaf33/parts
我收到以下错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{myapp/screens.car.CarActivity}: java.lang.IllegalStateException:
Activity screens.car.CarActivity@3b8d354 has null extras in Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://my-app.com/... flg=0x13008000 cmp=myapp/screens.car.CarActivity }
意图没有任何额外内容,但它应该包含在深层链接中定义为 URL 占位符的 carUuid
。一旦评估 navArgs()
就会抛出错误。
这是我的设置:
nav_graph.xml
<fragment
android:id="@+id/fragment_parts"
android:name="myapp.screens.parts.PartsFragment"
android:label="@string/parts"
tools:layout="@layout/fragment_parts">
<deepLink
android:id="@+id/deepLink"
app:uri="my-app.com/cars/{carUuid}/parts" />
<argument
android:name="carUuid"
app:argType="string" />
</fragment>
AndroidManifest
<activity android:name=".screens.car.CarActivity" >
<nav-graph android:value="@navigation/nav_graph" />
</activity>
CarActivity
class CarActivity : AppCompatActivity() {
private val carViewModel: CarViewModel by viewModel { parametersOf(args.carUuid) }
private val args: CarActivityArgs by navArgs()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DataBindingUtil.setContentView<ActivityCarBinding>(this, R.layout.activity_car).also { binding ->
binding.lifecycleOwner = this
binding.carViewModel = carViewModel
}
}
有用的链接:
Android documentation for implicit DeepLinks
----更新----
我创建了一个最小示例项目,并找到了有关 on/going 错误的提示。我在官方问题跟踪器上发布了所有内容:
https://issuetracker.google.com/issues/155690730
在你的深层链接中试试这个:
<fragment
android:id="@+id/fragment_parts"
android:name="myapp.screens.parts.PartsFragment"
android:label="@string/parts"
tools:layout="@layout/fragment_parts">
<argument
android:name="carUuid"
app:argType="string" />
<deepLink
android:id="@+id/deepLink"
app:uri="my-app.com/cars/{carUuid}/parts" >
</deepLink>
</fragment>
我从导航团队得到了答复,solution/workaround 对我的情况来说已经足够好了。可以在此处找到包括示例项目在内的更多详细信息
https://issuetracker.google.com/issues/155690730
为什么会这样(来自 Google 问题跟踪器的回答)
前往 SubActivity
内更深的 link 目的地绝对是可能的,但在 handleDeepLink()
时我们还没有构建 NavDeepLink
对象能够识别深层 link 变量。此外,如果我们能够以某种方式解析 URL 模式并将其作为额外的意图,对于您给出的示例,SubActivity
中的 by navArgs()
调用将 return "alice" 的值,它是指 link 深度目的地,而不是 Activity.
当您使用 NavDirections 调用 navigate() 时,by navArgs()
在 Activity 中工作的原因是因为 ActivityNavigator 将额外内容添加到用于启动新 Activity。当您使用来自 adb 的深度 link 时,您会绕过所有这些逻辑,这意味着启动 activity 的意图没有额外的内容,这就是它应该失败的原因。
无论您的用例是什么,都可能有比嵌套 Activities 更好的方法。话虽如此,您可以通过向用于从深层 link 启动应用程序的 adb 命令添加一个带有键名的额外命令来完成这项工作: --es "name" <"your string"> .
我现在做什么
我现在所做的,因为我可以完全控制 deeplink URLs,将 deeplink 设置为 SubActivity 本身。此外,我还提供了 deeplink URL 目标 SubActivity 应该设置为 startDestination.
的信息
这种方法对我来说效果很好。唯一的缺点是 MainActivity 也是在 backstack 中构建的,因此用户在按下后退按钮时首先被带回到这个 MainActivty。但我可以忍受:)
我想使用导航组件创建隐式深层链接。
但是当我使用以下 URL:
启动我的应用程序时https://my-app.com/cars/ef123-aaf33/parts
我收到以下错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{myapp/screens.car.CarActivity}: java.lang.IllegalStateException:
Activity screens.car.CarActivity@3b8d354 has null extras in Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=https://my-app.com/... flg=0x13008000 cmp=myapp/screens.car.CarActivity }
意图没有任何额外内容,但它应该包含在深层链接中定义为 URL 占位符的 carUuid
。一旦评估 navArgs()
就会抛出错误。
这是我的设置:
nav_graph.xml
<fragment
android:id="@+id/fragment_parts"
android:name="myapp.screens.parts.PartsFragment"
android:label="@string/parts"
tools:layout="@layout/fragment_parts">
<deepLink
android:id="@+id/deepLink"
app:uri="my-app.com/cars/{carUuid}/parts" />
<argument
android:name="carUuid"
app:argType="string" />
</fragment>
AndroidManifest
<activity android:name=".screens.car.CarActivity" >
<nav-graph android:value="@navigation/nav_graph" />
</activity>
CarActivity
class CarActivity : AppCompatActivity() {
private val carViewModel: CarViewModel by viewModel { parametersOf(args.carUuid) }
private val args: CarActivityArgs by navArgs()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DataBindingUtil.setContentView<ActivityCarBinding>(this, R.layout.activity_car).also { binding ->
binding.lifecycleOwner = this
binding.carViewModel = carViewModel
}
}
有用的链接:
Android documentation for implicit DeepLinks
----更新----
我创建了一个最小示例项目,并找到了有关 on/going 错误的提示。我在官方问题跟踪器上发布了所有内容: https://issuetracker.google.com/issues/155690730
在你的深层链接中试试这个:
<fragment
android:id="@+id/fragment_parts"
android:name="myapp.screens.parts.PartsFragment"
android:label="@string/parts"
tools:layout="@layout/fragment_parts">
<argument
android:name="carUuid"
app:argType="string" />
<deepLink
android:id="@+id/deepLink"
app:uri="my-app.com/cars/{carUuid}/parts" >
</deepLink>
</fragment>
我从导航团队得到了答复,solution/workaround 对我的情况来说已经足够好了。可以在此处找到包括示例项目在内的更多详细信息
https://issuetracker.google.com/issues/155690730
为什么会这样(来自 Google 问题跟踪器的回答)
前往 SubActivity
内更深的 link 目的地绝对是可能的,但在 handleDeepLink()
时我们还没有构建 NavDeepLink
对象能够识别深层 link 变量。此外,如果我们能够以某种方式解析 URL 模式并将其作为额外的意图,对于您给出的示例,SubActivity
中的 by navArgs()
调用将 return "alice" 的值,它是指 link 深度目的地,而不是 Activity.
当您使用 NavDirections 调用 navigate() 时,by navArgs()
在 Activity 中工作的原因是因为 ActivityNavigator 将额外内容添加到用于启动新 Activity。当您使用来自 adb 的深度 link 时,您会绕过所有这些逻辑,这意味着启动 activity 的意图没有额外的内容,这就是它应该失败的原因。
无论您的用例是什么,都可能有比嵌套 Activities 更好的方法。话虽如此,您可以通过向用于从深层 link 启动应用程序的 adb 命令添加一个带有键名的额外命令来完成这项工作: --es "name" <"your string"> .
我现在做什么
我现在所做的,因为我可以完全控制 deeplink URLs,将 deeplink 设置为 SubActivity 本身。此外,我还提供了 deeplink URL 目标 SubActivity 应该设置为 startDestination.
的信息这种方法对我来说效果很好。唯一的缺点是 MainActivity 也是在 backstack 中构建的,因此用户在按下后退按钮时首先被带回到这个 MainActivty。但我可以忍受:)