Android Permissions: A New Path to Glory

Egemen Hamutçu
Arabam Labs
Published in
6 min readMar 31, 2020
Petronas Twin Towers, Credits: https://flic.kr/p/eh5HrH

For more than 4 years, Android Permissions have devoured our time in development to provide our beloved users more transparent, and safer apps for Android platform.

This article is not a complaint but a new idea about the adventure of Android permissions. I don’t claim that the approach will cover all Android permission resolutions. The idea may probably be practiced by the most of you, but I am talking about creating a norm about it. If we can achieve this, the platform will overcome a considerable obstacle which is gathering storms in our brains.

As we all know, Android permissions requires lots of boilerplate code including massive AlertDialogs. I never liked them. They make the code too large and hard to read for me for years.

Some Android developers created useful libraries to reduce the number of lines in code. I used them too, but I am not really satisfied with their approach. I believe Android permissions are strongly related to business concerns, but those libraries focuses on just refactoring the code. Their approach is not easily manageable, and reusable. Moreover they don’t force us to provide a stable UX for our users. A typical Android user expects the same behavior for native platform events in every apps, as the Android platform itself expects us to maintain it too!

I don’t believe this can be handled by a third party library, but I believe that it can be resolved by a pattern. Android native permission process seems very low level for me according to our innocent activities and fragments. That should get high as much as possible so our activities and fragments can breathe fresh air.

This article will explain how we approached to permissions in Android app of arabam.com and show you our real code to provide a real experience that we faced. I will also provide a sample project on Github.

Let’s start from the highest point of our pattern: BusinessRequest

If you need an Android permission, you absolutely need to solve a business logic in your app, and the permission is probably sitting in the middle of it. That’s why BusinessRequest answers a base question: What are you going to do with these permissions?

Our activities and fragments will tell what they want to do using it. We also need to define the real permissions remaining in the settings menu:

We will map BusinessRequest to PermissionRequest later. These classes will help us better understand what permissions our business needs. More readable!

We need to identify our activities and fragments easily which are using permissions, so they will become children of abstract PermissionActivity, PermissionFragment and PermissionDialogFragment.

As you see we have 3 different abstract classes which they will do almost the same work. How can we manage them to do the same work without copying and pasting the code? The answer is, we need a manager class that will work as a field inside them and handle all business logic in one place and provide the same behavior in all permission requests in the entire app.

Our manager class will be PermissionManager. It will check whether permissions are granted, and show necessary dialogs like rationale & navigating to settings menu in case of user’s permanent denial. It will handle user choices and will let our 3 abstract classes know what happened in the end.

Wait a second, how can they know what happened in our mysterious PermissionManager class? We need a messenger between PermissionManager and 3 abstract classes. As you guess, we need a listener that will invoke essential events performed by PermissionManager. We call it PermissionListener.

Our architecture is ready, let’s see how it works to see the big picture:

Android Permission Architecture

Let’s start our adventure with an example for an Android permission process: When user wants to make a video call with an advertiser, s/he needs to give following permissions, Camera, Microphone & Phone. We have VideoCallActivity. It will extend PermissionActivity.

We will start calling checkPermissionsAreGranted(BusinessRequest.VIDEO_CALL, true) method implemented in PermissionActivity. It simply wants to make a video call, doesn’t worry about what permissions are needed. Lovely. Let’s see what happens in the method:

We pass optional parameter exitOnDenied true because the permissions are critical for VideoCallActivity. If user denies any of the permissions, we can’t do anything, so we will finish the activity in that case when exitOnDenied is true.

We put ourselves in PermissionManager‘s arms. It will call getPermissionRequestsFromBusiness(businessRequest) mapping BusinessRequest.VIDEO_CALL to an array of PermissionRequest.CAMERA, PermissionRequest.MICROPHONE and PermissionRequest.PHONE. Then, it will check whether all these permissions are granted by calling areAllPermissionsGranted(this, permissionRequests):

If all permissions are granted, it will simply call abstract function onPermissionsGranted(businessRequest) and VideoCallActivity will call makeVideoCall() function inside of it. However, if any of permissions are not granted yet, we will start preparation for permission process by calling prepareNativePermissionRequest(permissionsRequests).

It will prepare an Android’s native permission request; an array of strings including Manifest.permissions, and a requestCode integer value to match the result:

When they are ready, the function will let PermissionActivity know that the request is ready by invoking onNativePermissionRequestReady(permissions, requestCode) method. Then, PermissionActivity will simply call ActivityCompat.requestPermissions(this, permissions, requestCode) inside of it.

The result will fall into onRequestPermissionResult method inside PermissionActivity. Our superhero, PermissionManager comes along to aid us again! We call its handleRequestPermissionsResult(...) method to handle all the result logic for us:

It will check whether all permissions are granted. If user grants all permissions, it will let PermissionActivity know by invoking grantPermissions(businessRequest) method. If user denies any of permissions, it will check whether any of denied permissions should show a rationale dialog. If so, we will call showPermissionRationaleDialog(...), otherwise we must call showPermissionPermanentDenialDialog(...) because user denies all permissions permanently.

Rationale dialog will ask user to try again. If user taps on the positive button, it will invoke retry() method and all process will start over from checkPermissionsAreGranted(...) method. If user taps on the negative button, it will invoke deny() method and the process will be terminated.

Permanent Denial dialog will ask user to navigate to the settings menu of the application and grant necessary permissions for further process. If user taps on the positive button, it will invoke navigateToSettings() method and PermissionActivity will navigate to settings making isComingFromSettings as true to handle the result on onResume() method. (I once tried to handle it on onActivityResult but it was never called). If user taps on the negative button, it will invoke deny() method and the process will be terminated.

We handle the result by the following code in PermissionActivity:

PermissionManager helps us again with handleResume(this) to handle the result whether user grants permissions in the settings menu:

It will ask user to try again if s/he grants permissions in the settings menu. If user taps on the positive button, it will invoke retry() method and all process will start over from checkPermissionsAreGranted(...) method. If user taps on the negative button, it will invoke deny() method and the process will be terminated.

As you see, our VideoCallActivity did almost nothing about about the permission. Everything is handled by the help of PermissionActivity and PermissionManager.

Once upon a time, VideoCallActivity was quite fat and sad with permission works:

It had 136 lines of code, most of them work for permission issue. Our activities just don’t deserve this. Finally, it met with our savior PermissionManager and become a PermissionActivity:

Oh my goodness! We have now 22 lines of code. We saved a total number of 114 lines! Now VideoCallActivity happily lives ever after. This is just an example, imagine what happens when you apply this pattern in your entire project? I am curiously expecting your results!

I hope this article will open a new path to glory for approaching to Android permissions, making a platform-friendly applications to hold the users by our side.

I put a link to the sample repository for having the pattern in your projects. I certainly need your help and feedback to make the pattern much better, and cover more issues out of my sight.

--

--

Egemen Hamutçu
Arabam Labs

Android Developer at Paradox Cat, chaotic neutral, little prince of his little kingdom