Max*_*e C 5 android-jetpack-compose jetpack-compose-navigation
我想从通知操作按钮导航到撰写中的单个活动应用程序中的特定屏幕。根据此文档,我决定使用深层链接导航。问题是,当我单击通知操作按钮时,它会在导航到预期屏幕之前重新启动我的活动。如果我的活动在后台打开,我不希望它重新启动。
我就是这样做的:
这是我在应用程序清单中指定的内容:
<activity
android:name=".ui.AppActivity"
android:launchMode="standard"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myApp" android:host="screenRoute" />
</intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)
这是我的根导航图中的深层链接声明:
composable(
route = "screenRoute",
deepLinks = listOf(navDeepLink { uriPattern = "myApp://screenRoute" })
) {
ComposableScreen()
}
Run Code Online (Sandbox Code Playgroud)
这是我用于通知操作按钮的待处理意图:
val intent = Intent().apply {
action = Intent.ACTION_VIEW
data = "myApp://screenRoute".toUri()
}
val deepLinkPendingIntent = TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(1234, FLAG_UPDATE_CURRENT)
}
Run Code Online (Sandbox Code Playgroud)
我以为我在这里做错了什么,因为我没有找到任何关于这次重启的信息。因此,我下载了使用深层链接的官方撰写导航代码实验室(因为它也是单个应用程序活动),并且在使用来自意图的深层链接时执行相同的操作,活动将重新启动。
所以我的问题是:
谢谢
我在这里看到两个问题:
android:launchMode="singleTask" 我认为您的问题有多种解决方案。然而,这是一种可能的解决方案
为了确保您的应用程序始终拥有一个实例,您需要将 launchMode 设置为 singleTask
<activity
android:name=".ui.AppActivity"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myApp" android:host="screenRoute" />
</intent-filter>
</activity>
Run Code Online (Sandbox Code Playgroud)
当您的应用程序尚未启动并且您打开深层链接时,应用程序将启动并创建您的活动。因此,在 onStart 方法中,您将能够处理深层链接:
override fun onStart() {
super.onStart()
intent?.data?.let { /* handle deeplink */ }
// consume the deeplink
intent = null
}
Run Code Online (Sandbox Code Playgroud)
当您的应用程序已经运行时,单击深层链接会将应用程序带到前面,并会触发具有意图的观察者。
setContent {
DisposableEffect(Unit) {
val listener = Consumer<Intent> { intent ->
// Handle deeplink
}
addOnNewIntentListener(listener)
onDispose { removeOnNewIntentListener(listener) }
}
}
Run Code Online (Sandbox Code Playgroud)
在冷启动中,您不在可组合范围内。要解决此问题,您可以使用虚拟机作为视图的事件发射器。
class MyViewModel : ViewModel() {
val event = MutableStateFlow<Event>(Event.None)
fun handleDeeplink(uri: Uri) {
event.update { Event.NavigateWithDeeplink(uri) }
}
fun consumeEvent() {
event.update { Event.None }
}
}
sealed interface Event {
data class NavigateWithDeeplink(val deeplink: Uri) : Event
object None : Event
}
Run Code Online (Sandbox Code Playgroud)
冷启动情况下,调用该handleDeeplink(uri)方法
override fun onStart() {
super.onStart()
// To handle a cold deeplink intent we need to keep it and replace it with null
intent?.data?.let { myViewModel.handleDeeplink(it) }
intent = null
}
Run Code Online (Sandbox Code Playgroud)
在热启动情况下,也调用它
DisposableEffect(Unit) {
val listener = Consumer<Intent> { intent ->
intent.data?.let {
myViewModel.handleDeeplink(it)
}
}
addOnNewIntentListener(listener)
onDispose { removeOnNewIntentListener(listener) }
}
Run Code Online (Sandbox Code Playgroud)
现在,在您的主可组合项中,收集事件作为状态,并在收到事件时导航到深层链接。不要忘记使用它,因为我们在这里使用 stateFlow。
val event by myViewModel.event.collectAsState()
LaunchedEffect(event) {
when (val currentEvent = event) {
is Event.NavigateWithDeeplink -> navController.navigate(currentEvent.deeplink)
Event.None -> Unit
}
myViewModel.consumeEvent()
}
Run Code Online (Sandbox Code Playgroud)
就像我说的,使用 TaskStackBuilder 将重新创建一个活动。您可以自己创建,而不是使用它来创建待处理的意图
val routeIntent = Intent(
Intent.ACTION_VIEW,
MyUri
).apply {
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
}
val flags = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
val pending = PendingIntent.getActivity(
appContext,
0,
routeIntent,
flags
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2589 次 |
| 最近记录: |