Android13では同意が必要(追記)
Android13、TargetSDKが33の場合には、ユーザー同意が必要になっていました。
ユーザー同意を得ないとNotificationは機能しません。
ユーザ同意を得るためのコードが以下の通りです。
// ランタイムパーミッションの結果.
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
if (it) {
// 権限が許可されたので、該当の権限が必要な操作が可能.
println("ok")
} else {
// 権限が拒否されたので、該当の権限が必要な操作が不可.
println("permit denied")
}
}
private fun checkNotificationPermission() {
// OS バージョン確認.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
// Android 13 未満は通知権限不要.
return
}
// 通知権限が許可されているか確認.
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
// 権限許可済.
return
}
// 通知権限を必要とする理由をアプリが提示する必要があるか確認.
if (shouldShowRequestPermissionRationale(
Manifest.permission.POST_NOTIFICATIONS)) {
// 必要がある場合は、その理由を説明するためのUIを明示的に表示する.
return
}
// 通知権限をリクエストする.
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
通知を出すためのコード
Notification(通知)を出して通知ドロワーに通知する機能を作ってみた。
以下のようにAndroid12の端末で動かせたのでご参考までに共有します。

通知を出すと、音量をオフにしていても「ピコーン!」と音がするので、何かお知らせする時には便利だ。
コードを紹介していきます。
API26以上の場合、NotificationChannelを作成する必要がある。
private val channelId = "hoge"
private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "a"
val descriptionText = "b"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(channelId, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
チャネルのIDや名前はなぜ設定する必要があるのか分からないが、適当に設定しても通知は出せたので気にしないことにする。
次に通知を出すところ。
private fun showNotification(){
createNotificationChannel()
// タップ時に起動する画面を設定
val intent = Intent(this, MainActivity::class.java)
//既存のアクティビティを起動する
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
//既存のアクティビティを消して、新しくアクティビティを作成する
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val builder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(android.R.drawable.btn_star)
.setContentTitle("落下しましたよ!!!")
.setContentText("スマホが落下したようです!!!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
val notificationManagerCompat = NotificationManagerCompat.from(this)
notificationManagerCompat.notify(R.string.app_name, builder.build())
}
通知を出すだけなら、インテントの設定は必要ない。
私の場合は、通知のタップをした時に起動中の画面に遷移したかったので、以下の設定をした。
- インテントを作成
- 起動中のActivity画面に遷移するようにフラグでSINGLE_TOPを指定
- pendingIntentにインテントをセット
- pendingintentをビルダーに設定
通知を出すだけなら簡単では?と思っていたが意外と難しかった。
つまづいた点は以下の通り。
- 通知チャネルを作成しておらず通知が出ない
- チャネルIDに何を設定して良いか分からない。
- 通知をタップしたときに、Acitivityが再起動してしまう。
- 通知をタップしたときに、起動中のAcitivityに遷移する方法が分からない。
1日がかりでStackOverflowを調べて解決した。