Отправить аргумент через PendingIntent NavDeepLinkBuilder
У меня возникли трудности с отправкой аргумента через PendingIntent
уведомления с использованием NavDeepLinkBuilder
, Я могу получить пункт назначения Activity
запустить, нажав на уведомление, но Activity
"s Intent
не содержит значение аргумента, которое я передал через NavDeepLinkBuilder
, Intent
вместо этого возвращает defaultValue
что я установил в графе навигации - "noJobId".
Создание уведомления:
val notification =
NotificationCompat.Builder(context, context.getString(R.string.notification_channel_id_new_job))
.setSmallIcon(R.drawable.icon_launcher)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(contentView)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setOngoing(true)
.setSound(getAlertSoundUri(context))
.setVibrate(vibrationPattern)
.setContentIntent(
NavDeepLinkBuilder(context)
.setComponentName(NewJobDetailsActivity::class.java)
.setGraph(R.navigation.main_graph)
.setDestination(R.id.newJobDetailsActivity)
.setArguments(
NewJobDetailsActivityArgs.Builder()
.setJobId(event.jobId)
.build()
.toBundle()
)
.createPendingIntent()
)
.setDeleteIntent(
PendingIntent.getBroadcast(
context,
0,
Intent(context, NewJobNotificationRemovalReceiver::class.java).apply {
action = NewJobNotificationRemovalReceiver.ACTION_CLEARED
putExtra(NewJobNotificationRemovalReceiver.EXTRA_JOB_ID, event.jobId)
},
0
)
)
.build()
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE and Notification.FLAG_INSISTENT
notificationManager.notify(notificationId, notification)
context
используется в уведомлении FirebaseMessagingService
,
Место назначения Activity
onCreate()
:
val jobId: String = NewJobDetailsActivityArgs.fromBundle(intent?.extras).jobId
main_graph.xml
Навигационный график:
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_graph"
app:startDestination="@id/jobsFragment">
<fragment
android:id="@+id/jobsFragment"
android:name=".ui.jobs.JobsFragment"
android:label="JobsFragment">
<action
android:id="@+id/action_jobsFragment_to_newJobDetailsActivity"
app:destination="@id/newJobDetailsActivity" />
</fragment>
<fragment
android:id="@+id/historyFragment"
android:name=".ui.history.HistoryFragment"
android:label="HistoryFragment" />
<fragment
android:id="@+id/profileFragment"
android:name=".ui.profile.ProfileFragment"
android:label="ProfileFragment" />
<activity
android:id="@+id/newJobDetailsActivity"
android:name=".ui.job.NewJobDetailsActivity"
android:label="activity_new_job_details"
tools:layout="@layout/activity_new_job_details">
<argument
android:name="jobId"
android:defaultValue="noJobId" // just for testing
app:argType="string" />
</activity>
</navigation>
Кто-нибудь еще сталкивался с этой проблемой? Я чувствую, что это ошибка в компоненте навигации, но я еще не уверен на 100%. Любопытно, есть ли что-то, что я здесь упускаю.
Зависимости: android.arch.navigation: navigation-фрагмент-ktx:1.0.0-alpha06, android.arch.navigation:navigation-ui-ktx:1.0.0-alpha06
Плагин: androidx.navigation.safeargs
3 ответа
Я разместил эту проблему на общедоступном трекере Google и получил следующий ответ:
NavDeepLinkBuilder передает свои аргументы в NavController для глубокой связи в конкретное место назначения. Направления деятельности - это действительно больше точек выхода из графика навигации, чем то, с чем можно / должно быть тесно связано.
Источник: https://issuetracker.google.com/issues/118964253
Автор этой цитаты рекомендует использовать TaskStackBuilder
вместо NavDeepLinkBuilder
при создании PendingIntent
чей пункт назначения Activity
, Вот то, что я закончил с:
NotificationCompat.Builder(context, context.getString(R.string.notification_channel_id_new_job))
...
.setContentIntent(
TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(Intent(context, DestinationActivity::class.java).apply {
putExtras(DestinationActivityArgs.Builder(jobId).build().toBundle())
})
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
)
.build()
Это решение позволяет мне успешно глубокую ссылку на пункт назначения Activity
все еще будучи в состоянии ссылаться на аргументы, определенные в графике навигации для этого Activity
через сгенерированный DestinationActivityArgs
строитель и доступ к аргументам из пункта назначения Activity
"s onCreate()
метод работает.
Это решение также правильно обрабатывает случаи, когда задача приложения отсутствует в списке "недавних приложений", приложение на переднем плане показывает некоторые другие Activity
или же Fragment
или приложение находится на переднем плане и уже находится в пункте назначения Activity
, addNextIntentWithParentStack()
правильно обрабатывает навигацию, поэтому нажимая кнопку вверх от пункта назначения Activity
возвращается к логическому родителю Activity
как определено в AndroidManifest
,
Немного огорчает, что это решение не использует библиотеку Navigation Architecture для создания PendingIntent
, но это похоже на лучшую альтернативу.
Вы можете найти все аргументы, которые вы отправляете в arguments
переменная вашего Activity/Fragment.
Вот пример того, как получить String
аргумент установлен в PendingIntent, созданный NavDeepLinkBuilder() с ключомEVENT_KEY
в месте назначения Activity/Fragment:
requireArguments().getString(YourClass.EVENT_KEY)?.let { it } ?: ""
Обратите внимание, что наш getString()
вызов может вернуть значение null, если искомого значения нет, поэтому убедитесь, что Bundle
вы в конечном итоге назначаете NavDeepLinkBulder().setArguments()
заполняется так, как вы этого хотите!
У меня была такая же проблема, мой пакет всегда возвращал null, это то, что у меня сработало:
В моем фрагменте у меня есть метод, который передает пакет:
notificationManager.sendNotification( requireArguments(), // This gets me the arguments supplied when the fragment in instantiated requireContext() )
В моем уведомленииUtils мое намерение контента:
fun NotificationManager.sendNotification( bundle: Bundle, appContext: Context ) { val contentIntent = NavDeepLinkBuilder(appContext) .setComponentName(MainActivity::class.java) .setGraph(R.navigation.navigation) .setDestination(R.id.detailsFragment) .setArguments(bundle) .createPendingIntent() // Rest of code to build the notification... }
Чтобы проверить правильность передачи пакета, я зарегистрировал следующее:
Timber.d("The name is: ${bundle.getParcelable<Person>("Person")?.name}")