Keeping Android runtime permissions from cluttering your app (Headless Dialog Fragments!)

Tyler Roach
AndroidPub
Published in
2 min readSep 1, 2016

--

I know I’m late to the party implementing Android runtime permissions in the Stream app. We had our reasons for this, but now that Nougat has been released, its time we upgrade our targetSdkVersion to 24.

I’m not a huge fan of the design for runtime permissions. It can quickly clutter your activity/fragment code as you have to handle multiple grant scenarios with proper messaging to the user. In order to combat this, I decided to contain nearly all aspects of permission management inside headless dialog fragments.

To show how this works, I’ve created an example app that demonstrates how to request all necessary permissions to record videos (camera, mic, and storage). The full source code can be found here for reference: https://github.com/tylerjroach/RuntimePermissionsExample. Lets go ahead and look at the entire CameraPermissionsDialogFragment source.

In onCreate(), we call requestNecessaryPermissions(). This prompts the user to deny/allow each requested permission, and the results are passed to onRequestPermissionResult(). In this example, we are checking for 3 possible scenarios:

  1. All permissions accepted
  2. One or more permissions denied
  3. One or more permissions denied and “Don’t ask again” checked

Regardless of the outcome, you will want to be careful in what you update in onRequestPermissionResult(). The results are passed down to this method while the app is in a paused state. As a result, certain actions can cause a crash (Ex. IllegalStateException from a FragmentTransaction commit). To work around this, I set boolean flags on the action to take, and built onResume() to handle the action once the app is back into the foreground. This will guarantee that fragment transactions will be safe to run, and the ui will be safe to update.

Now, lets go back to our activity that is requesting the runtime permissions. You can see that the activity is only responsible for checking if any permissions are needed before opening the camera. You can see how the activity code could quickly become cluttered if we didn’t separate the permission requests into our DialogFragment.

Side notes:

  • I used a DialogFragment, however, a standard Headless Fragment could have worked as well. I chose to use a dialog fragment because setCancelable(false) can easily prevent all outside touches, as well as the simple creation/destruction with show() and dismiss().
  • By default, a DialogFragment dims the screen background content. To remove this, simply use this style on the dialog.
<style name="PermissionsDialogFragmentStyle" parent="Base.Theme.AppCompat.Dialog">
<item name="android:backgroundDimEnabled">false</item>
</style>

I look forward to reading any comments or questions you may have! If this post was helpful, please ❤

--

--

Tyler Roach
AndroidPub

Lead Android Developer for http://stream.live (Twitter @stream) | Appterial, LLC (Owner) | Indiana University School of Informatics Grad