Here is the complete example of how can you ask run time permission for notifications in Android 13 (Tiramisu)
First, add the below permission in your manifest
file
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
Use the below code to ask for run time permission
package com.example.myapplication
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
import android.widget.Button
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.NotificationCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
class MainActivity : AppCompatActivity() {
private val notificationPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
hasNotificationPermissionGranted = isGranted
if (!isGranted) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= 33) {
if (shouldShowRequestPermissionRationale(android.Manifest.permission.POST_NOTIFICATIONS)) {
showNotificationPermissionRationale()
} else {
showSettingDialog()
}
}
}
} else {
Toast.makeText(applicationContext, "notification permission granted", Toast.LENGTH_SHORT)
.show()
}
}
private fun showSettingDialog() {
MaterialAlertDialogBuilder(this, com.google.android.material.R.style.MaterialAlertDialog_Material3)
.setTitle("Notification Permission")
.setMessage("Notification permission is required, Please allow notification permission from setting")
.setPositiveButton("Ok") { _, _ ->
val intent = Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
}
.setNegativeButton("Cancel", null)
.show()
}
private fun showNotificationPermissionRationale() {
MaterialAlertDialogBuilder(this, com.google.android.material.R.style.MaterialAlertDialog_Material3)
.setTitle("Alert")
.setMessage("Notification permission is required, to show notification")
.setPositiveButton("Ok") { _, _ ->
if (Build.VERSION.SDK_INT >= 33) {
notificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
}
}
.setNegativeButton("Cancel", null)
.show()
}
var hasNotificationPermissionGranted = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.btnRequestPermission).setOnClickListener {
if (Build.VERSION.SDK_INT >= 33) {
notificationPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
} else {
hasNotificationPermissionGranted = true
}
}
findViewById<Button>(R.id.btnShowNotification).setOnClickListener {
if (checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
showNotification()
}
}
}
private fun showNotification() {
val channelId = "12345"
val description = "Test Notification"
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel =
NotificationChannel(channelId, description, NotificationManager.IMPORTANCE_HIGH)
notificationChannel.lightColor = Color.BLUE
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
}
val builder = NotificationCompat.Builder(this, channelId)
.setContentTitle("Hello World")
.setContentText("Test Notification")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(
BitmapFactory.decodeResource(
this.resources, R.drawable
.ic_launcher_background
)
)
notificationManager.notify(12345, builder.build())
}
}
If you using jetpack compose then user below code
class MainActivity : ComponentActivity() {
@RequiresApi(VERSION_CODES.M)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposeNotifcationPermissionTheme {
val context = LocalContext.current
val permissionOpenDialog = remember { mutableStateOf(false) }
val rationalPermissionOpenDialog = remember { mutableStateOf(false) }
if (permissionOpenDialog.value) {
ShowSettingDialog(openDialog = permissionOpenDialog)
}
var hasNotificationPermission by remember {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
mutableStateOf(
ContextCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
)
} else mutableStateOf(true)
}
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { isGranted ->
if (!isGranted) {
if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
rationalPermissionOpenDialog.value = true
} else {
permissionOpenDialog.value = true
}
} else {
hasNotificationPermission = isGranted
}
}
)
if (rationalPermissionOpenDialog.value) {
ShowRationalPermissionDialog(openDialog = rationalPermissionOpenDialog) {
rationalPermissionOpenDialog.value = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}) {
Text(text = "Request permission")
}
Button(onClick = {
if (hasNotificationPermission) {
showNotification()
}
}) {
Text(text = "Show notification")
}
}
}
}
}
private fun showNotification() {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "12345"
val description = "Test Notification"
if (VERSION.SDK_INT >= VERSION_CODES.O) {
val notificationChannel =
NotificationChannel(channelId, description, NotificationManager.IMPORTANCE_HIGH)
notificationChannel.lightColor = Color.BLUE
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
}
val notification = NotificationCompat.Builder(applicationContext, channelId)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Hello Nilesh")
.setContentText("Test Notification")
.build()
notificationManager.notify(1, notification)
}
@Composable
fun ShowSettingDialog(openDialog: MutableState<Boolean>) {
if (openDialog.value) {
AlertDialog(
onDismissRequest = {
openDialog.value = false
},
title = {
Text(text = "Notification Permission")
},
text = {
Text("Notification permission is required, Please allow notification permission from setting")
},
buttons = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("Cancel")
}
Spacer(modifier = Modifier.width(20.dp))
TextButton(
onClick = {
openDialog.value = false
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
},
) {
Text("Ok")
}
}
},
)
}
}
@Composable
fun ShowRationalPermissionDialog(openDialog: MutableState<Boolean>, onclick: () -> Unit) {
if (openDialog.value) {
AlertDialog(
onDismissRequest = {
openDialog.value = false
},
title = {
Text(text = "Alert")
},
text = {
Text("Notification permission is required, to show notification")
},
buttons = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
TextButton(
onClick = {
openDialog.value = false
}
) {
Text("Cancel")
}
Spacer(modifier = Modifier.width(20.dp))
TextButton(
onClick = onclick,
) {
Text("Ok")
}
}
},
)
}
}
}