Notification permission request on Android 13 (Part 1 — the flow)

Patryk Kubiak
8 min readJan 18, 2023
Photo by Kelly Sikkema on Unsplash

Introduction

In this article, we will go through a general explanation, flow, and implementation of the notification permission request. I’ve gathered all of the information gained during the various request implementations. I encourage you to read it all because there are many minor things that you may miss during the process. I had to learn from my mistakes. Therefore, I hope you won’t have to do it 😉

It’s a complex topic, so I divided it into parts and sections:

Part 1 — the flow <- you are reading this part

  • The notification permission general description
  • Basic rules and information
  • The permission request flow
  • Google’s recommended flow
  • Q&A

Part 2 — the implementation

  • The implementation basics
  • The implementation in Activity/Fragment
  • The implementation in Jetpack Compose
  • The implementation with Accompanist

The notification permission

Starting from Android 13, we may notice a new permission to handle in the app — the notification permission. From a user perspective we may be satisfied that the notifications are turned off for every new app by default. It helps to avoid receiving any unwanted notices and focus on the right things. On the other hand, from a developer perspective, we have an additional thing to handle and maintain in the code.

So, in brief, let’s assume we are in the “halfway happy” state.

Basic rules and information

Here are some basic rules for new notification permission:

  • the notification permission is available from SDK 33 (Android 13). If our app on Android 13 is built with compileSdk = 32 , then we still don’t have to handle the notification permission request. The reason is that notifications will be turned on by default. However, be aware that we can have the targetSdk only two versions below the latest. So, sooner or later, we have to handle the notification permission request!
  • A device upgraded from Android 12 to Android 13 (from SDK 32 to 33) doesn’t change the notification permission grant status. By default, every app on Android 12 and below has the notification permission granted as default. However, the user may change that in the app settings. If the user has been granted the app permission before the device upgrade, then the app still has the notification permission on Android 13.
  • The shouldShowRequestPermissionRationale() method does not return true by default. Before the system notification permission requests it returns false. I will explain this later in the flow section. However, in brief — it allows us to show a rationale only after the first denial. I’ve put a simple image with the differences.
  • We should request the notification permission after user interaction requires it. For example, while clicking a button that sets AlarmManager with a future date to show a notification. We can apply this moment for requesting notification permission basically for every permission. On the other hand, we may not have any places to request the notification after. It may be set after launching the app. I’ve described that case in the second part of the article in the Q&A section.

The permission request flow

Different flows

There are many different flows that we can follow with our notification permission request implementation, however, I will explain fully a single one — the one which Google recommends.

In this flow, we will use the shouldShowRequestPermissionRationale(permission) system method that determines the presence of custom rationale.

For example, in a different flow, we can show a rationale even before the first request. We can achieve that with some custom values stored in shared preferences, but at this point, let’s stick to Google’s recommended flow by using the shouldShowRequestPermissionRationale(permission) method.

Google’s recommended flow

Let’s see the flow graphic and go straight to the description below.

We can implement two or three attempts of control. The third one is optional, as we don’t have to handle the forever denied case separately. However, I strongly recommend holding this attempt as well.

1. The first attempt

At the beginning of the first attempt, we should check if we already have permission for our app. Otherwise, we request it without any additional information. If we do that after the user interaction, the user may grant permission without additional information. We can imagine that after clicking the “notify me” button, the notification permission request is an intuitive thing to ask. If the user grants permission, we also have access to it.

In another case, the system changes the permission status to “denied”. With denial status, we can decrease the app’s experience by disabling some options or moving to the previous screen in the app. It shouldn’t be done too aggressively, so don’t close the entire app if you don’t have to 😄 It’s good to decrease the user experience as less as possible. Moving back, if the user denies the request, we would go to the second attempt step.

2. The second attempt

After the first denial, we should show a rationale with an explanation of why we need the requested permission. We should do that because users may be not aware of the permission purpose in our app. The rationale may be a custom dialog informing before the system permission request. I believe it’s better to make the dialog window not dismissable on clicking outside the space. In case the user clicks somewhere unwittingly.

If the user denies the permission a second time, the system changes its status to “forever denied”. Accordingly, the request will not appear again. 😔

3. Next steps for forever denied case

The third request is not possible. However, we can display something else instead of the system request. The third option is marked as optional because it requires even more work from us to implement.

Often requests may annoy users. Although, the users may change their mind. Then, they need help with granting permission to the app.

What can we do if we cannot show the system request?

For example, we can implement a separate dialog with information on how to change the permission manually from the settings. Then, for the positive action button, we can attach Intent which goes straight to the app settings. This step is additional work, but it may be worth it. Especially, if we value the notification permission. For example, we would like to increase the number of received push notifications from the Firebase.

Q&A

1. How to distinguish the forever denied case from the first request case?

We can store a boolean value in shared preferences and just change the value after the first permission request. With that, we can handle these cases separately.

2. Are there more request flows available?

Yes, there are more cases. I mentioned about one additional at the beginning of this article.

Moving back to a different flow, we can show for example a rationale just before the first request. This should increase our chances of granting permission if we truly want permission from the user. We are used to granting permission which may be strictly connected with the app functionality. So, it’s normal for us that taking picture functionality requires camera permission. Let’s assume another case where granting permission is not so obvious. Then the user may think “why the app asks about this permission” but with the first request and the normal flow there is no answer to that question. In that case, showing a rationale even before the first flow may be a good idea because the user will see a rationale twice. Unfortunately, there is no easy way to achieve this behavior and to implement that we would resign from the shouldShowRequestPermissionRationale(permission) method and replace it with our custom conditions with values stored in the SharedPreferences .

3. When and how often should we show popups?

It basically depends on that if we request the notification permission after the user interaction or not.

In case of user interaction

Let’s imagine that we request notification permission after the “notify me” button click. We should request permission after the “notify me” button clicks every time because the button name says explicitly that the main action after the button click is notifying the user. In case of denying forever the notification permission, we may show the “go to settings to enable the permission” dialog.

Now, let’s imagine that the button text is just a “save” and after clicking the button we are saving an item on our list. Furthermore, in the background, we would like to schedule an additional reminder notification as an optional extra. In that case, the user may not understand why we need the notification permission because it’s not so obvious. In case of denial, we may show the request after the next button press or just after some threshold. We don’t care so much about the specific reminders, so we can ask the user for permission just after some time. Why? Because at the beginning nobody likes many popups. In most cases, if we can postpone the popup then we should do it to not overload the user with the popups. With less popup overloading, we have a higher chance of attention and our rationale may be more important to the user.

Requesting permission at the app launch

We may have an app that is created for receiving the notifications from the API, for example, we want to display the Firebase Push Messages. The user may log in to the app and then we can request permission for the first time. Unfortunately, let’s assume that the user would deny our request. What should we do then if the user is logged in in the next session?

Then we would like to request permission after the launch of the app. It’s not a recommended option because there is no informing action connected to the permission, however, sometimes the app may be a good explanation itself if our main goal would be to show notifications. So, in that case, let’s show the rationale after the app launch and then request permission. In the case of the second denial, probably we would have to decrease the user experience.

4. What should we do if we show the Firebase messages?

Firebase adds POST_NOTIFICATION permission to our AndroidManifest.xml file. Unfortunately, we have to handle the notification permission request anyway. If we care much about the notifications we should request permission as soon as possible after identifying the user. For more info about the behavior let’s look at the 3rd point of the Q&A section.

Summary

Uff… We went together through a lot of information! Congrats and thanks for your patience!

After the first part with theoretical knowledge about notification permission, we know:

  • why and when should we implement the notification permission request
  • there are many flows for requesting the notification permission
  • how does Google’s recommended flow for requesting the notification permission work precisely
  • what should be implemented in various cases depends on our specific app needs
  • and much more! I am sure that that information mentioned there will let you save time during the implementation 😁

--

--

Patryk Kubiak

Android Developer from Poland, working in Espeo Software.