Android(Kotlin)Navigation 通知タップで遷移
2020/9/1
はじめに
過去の記事で 、Navigation コンポーネントでアプリバーを実装しました。今回は「通知タップで目的のデスティネーションへ遷移」を実装してみます。 (後述する差分は前述記事からの差分になります)。
実装内容
概要
通知タップアクションと遷移を紐付けるには、ドキュメント記載の通り、遷移用 PendingIntent
を用意すれば良いです。
Navigation コンポーネントにおいては、ディープリンクが用意されているので、今回は明示的ディープリンクとしての PendingIntent
を作成します。
差分
app/src/main/java/com/example/myapplication/FirstFragment.kt
通知の処理詳細はともかく、ここで重要なのは NavDeepLinkBuilder
で PendingIntent
を作成し、それを setContentIntent
していることです。
チャネル作成に関しては通知ドキュメント記載のサンプルコードを機械的に持って来ていますので細かいことは気にしないでください。
@@ -1,11 +1,18 @@
package com.example.myapplication
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.Fragment
+import androidx.navigation.NavDeepLinkBuilder
import androidx.navigation.findNavController
class FirstFragment : Fragment() {
@@ -20,6 +27,45 @@ class FirstFragment : Fragment() {
it.findNavController().navigate(action)
}
}
+ findViewById<Button>(R.id.first_notification_button).apply {
+ setOnClickListener {
+ val notificationId = 0 // 動作確認のためだけに適当に。
+ val context = requireContext()
+ createNotificationChannel(context)
+ val pendingIntent = NavDeepLinkBuilder(context)
+ .setGraph(R.navigation.nav_graph)
+ .setDestination(R.id.secondFragment)
+ .createPendingIntent()
+ val builder = NotificationCompat.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_launcher_foreground)
+ .setContentTitle("タイトル")
+ .setContentText("内容")
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setContentIntent(pendingIntent)
+ .setAutoCancel(true)
+ with(NotificationManagerCompat.from(context)) {
+ notify(notificationId, builder.build())
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val CHANNEL_ID = "CHANNEL_ID"
+ }
+
+ private fun createNotificationChannel(context: Context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = getString(R.string.channel_name)
+ val descriptionText = getString(R.string.channel_description)
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
+ description = descriptionText
+ }
+ val notificationManager: NotificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
}
}
}
app/src/main/res/layout/fragment_first.xml
通知を表示するためのボタンを用意しただけです。
@@ -11,6 +11,12 @@
android:layout_height="wrap_content"
android:text="first_fragment" />
+ <Button
+ android:id="@+id/first_notification_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Notification" />
+
<Button
android:id="@+id/first_button"
android:layout_width="wrap_content"
app/src/main/res/values/strings.xml
持ってきた通知チャネル作成サンプルコードに応じて設定を追加しただけです。
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 82d06a3..c573279 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2,4 +2,6 @@
<string name="app_name">My Application</string>
<string name="destination_first">画面1</string>
<string name="destination_second">画面2</string>
+ <string name="channel_name">channel_name</string>
+ <string name="channel_description">channel_description</string>
</resources>
補足
遷移時に引数が必要な場合は下記の通り、Safe Args
により生成された引数クラスをインスタンス化し、toBundle()
したものを setArguments
してあげれば良いみたいです。
val pendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.secondFragment)
.setArguments(SecondFragmentArgs(arg).toBundle())
.createPendingIntent()