来自前台服务的 Nav Deep Link

Nav Deep Link from a foreground service

我正在尝试从前台服务通知导航到我的导航图中的片段。我使用下面的代码创建了一个显式的深度 link,但没有按预期运行。

val pendingIntent = NavDeepLinkBuilder(this) // this is the Service context!
            .setComponentName(MainActivity::class.java)
            .setGraph(R.navigation.primary_app_nav)
            .setDestination(R.id.shareSheetFragment)
            .setArguments(bundle)
            .createPendingIntent()

阅读 guide 后,我了解到您需要使用 activity 上下文而不是任何其他上下文(在我的例子中是服务上下文)。

Note that if the provided context is not an Activity, the constructor uses PackageManager.getLaunchIntentForPackage() as the default activity to launch, if available.

我的问题是如何从我的前台服务中获取 MainActivity 上下文?

我仍然没有找到一种方法来使用显式深度 links,但我选择了一种利用隐式深度 link.

的解决方案

首先,在导航图中向您的片段添加深度 link XML。

<deepLink android:id="@+id/deepLink"
   app:uri="my-app://com.example.app/hotspot?ssid={ssid}&amp;passkey={passkey}" />

在清单中的 <activity /> 中添加 <nav-graph /> 标签。这将确保创建所有 Intent 过滤器并将其合并到您的清单中。

<nav-graph android:value="@navigation/primary_app_nav" />

按如下方式为通知创建 PendingIntent

fun getNotificationPendingIntent(ssid: String, passkey: String): PendingIntent {
     val uri = Uri.parse("my-app://com.example.app/hotspot?ssid=$ssid&passkey=$passkey")
     val bundle = Bundle().apply { putParcelable(SHARE_DEEP_LINK_KEY, uri) }
     val intent = Intent(this, SailsActivity::class.java).apply {
          putExtras(bundle)
          // to clear the back stack
          addFlags(FLAG_ACTIVITY_CLEAR_TOP or FLAG_ACTIVITY_SINGLE_TOP
                     or FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK)
     }
     return PendingIntent.getActivity(this, launchShareSheetCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}

最后,您需要处理来自 Activity class' onCreate() 方法的深层 link 意图。

private fun handleDeepLinkIntent() {
    val deepLink = intent.extras?.getParcelable(SHARE_DEEP_LINK_KEY) as? Uri
    deepLink?.also {
        val intent = Intent(this, SenderService::class.java)
        this.bindService(intent, serviceConn, Context.BIND_ABOVE_CLIENT)
        navigateDeepLink(it)
    }
}

private fun navigateDeepLink(uri: Uri) {
    findNavController(R.id.navHostFragment).apply {
        if (graph.hasDeepLink(uri)) 
            navigate(uri)
        else {
            currentDestination?.getAction(id)?.let {
                navigate(id)
            }
        }
    }
}

深度 link URI 参数在目标片段中自动提供给您。

if (arguments != null) {
     val ssid = requireArguments().getString("ssid")
     val passkey = requireArguments().getString("passkey")
}