Use headless Fragment for Android M run-time permissions and to check network connectivity

Headless fragments are a great alternative to using a base Activity to hold common code in your app. In this article I hope to explain the problem with base Activities and give you an example of a few different ways in which I have used headless fragments, including to handle runtime permissions in Android M.

Ali Muzaffar

--

One great rule to follow when writing your code, is to think about how it would look to someone who is not familiar with the code and logic. You may know why you took certain code architecture and design decisions, however, if it requires understanding beyond what someone sees in the code, either leave a comment or don’t do it. With this in mind, lets see what the issue with base Activities can be.

What’s wrong with base Activities

Base Activities use inheritance to provide logic that is supposed to be common across various activities. The idea being that all activities that require that functionality will inherit from the same activities and save you having to write the same bit of logic again and again. The first problem that comes up in any sizeable project is that your BaseActivity ends up holding a lot of code that may not be needed by each Activity. If this code does something like listen for back stack changes and manipulates nav bar options and Activity titles, you may need to add boolean flags to enable of disable features. This creates a maintenance overhead and any new developer coming on board will have no idea what is going on.

You may be tempted to use helper classes in order to work around the issue where you have code being inherited that is not required by an Activity, or providing functionality counter to what you may want. However, for helper classes, this can mean passing instances of Activity or Context which can cause memory leak issues, especially if asynchronous processing and callbacks are involved. Further, these classes are not life-cycle aware and you would have to code this behaviour yourself. Understandably, this is messy. That being said, headless fragment that are discussed below are effectively helper classes, except they are context and life-cycle aware.

Further, your BaseActivity may extend AppCompatActivity and you may come across use cases where you want to extend a regular Activity, ListActivity or PreferenceActivity. In this case, you’ll have no choice but to duplicate your code.

Enter headless Fragments

A headless Fragment is simply a Fragment that does not have a layout or View to render. Fragments are also context and life-cycle aware and with setRetainInstance() set to true, they are not destroyed and recreated on orientation changes. This makes them ideal candidates for holding reusable logic whether it relies of life-cycle methods or not. It also makes them a great place to perform asynchronous tasks as they are not destroyed on Activity orientation changes and hence even through the Activity life-cycle your long running process can execute and deliver the result when the Fragment is reattached. Effectively, they are fancy helper classes.

If you want a stronger argument for using headless Fragments or for using Composition over Inheritance, which is effectively what the argument in favor of headless Fragments boils down to, read this Google+ post by Josh Brown.

Headless fragment strategy

If you create one Fragment which contains all your common code, then this sort of defeats the purpose. The idea behind headless fragments is that you create a Fragment for each feature you want to implement and then depending on the features you need, you just add the appropriate Fragment to your Activity. Below I show you how to create 2 different headless fragments.

  • Headless fragment to check internet availability.
  • Headless fragment to request Android-M run-time permissions.

Adding a headless fragment to your Activity

You add a headless Fragment to your activity the same way that you would any other Fragment. Keep in mind though that you have set setRetainInstance() to true and so if your activity is destroyed and recreated, you need to check if your fragment exists and if so, re-attach it. The code for this looks like so:

mHeadlessFrag = (MyHeadlessFragment) getFragmentManager()
.findFragmentByTag(NetworkHelper.TAG);
if (mHeadlessFrag == null) {
mHeadlessFrag = MyHeadlessFragment.newInstance();
getFragmentManager().beginTransaction()
.add(mHeadlessFrag, MyHeadlessFragment.TAG)
.commit();
}

Using headless Fragments

You can either call methods in a headless Fragment directly, or declare a callback for the headless fragment to return a value in. By default, the callback approach is used by all Fragments to communicate with Activities and this is not a bad approach to use, however, depending on your use case, you may want to call a method directly and get a result.

Headless fragment to check internet availability

Your app does not always need to know whether internet connectivity is available, however, when it needs to check on a screen whether internet connectivity is available, you can use something like the code below [gist link].

After you have created your headless Fragment, you can add it to any Activity that needs to check for an internet connection and call the isInternetConnected() method to check for internet connectivity. In this above code, the method is static, however, since the Fragment has access to the current context, you can call getActivity() or getContext() directly and don’t need to make the isInternetConnected() method static. I usually define a BroadcastReceiver in my manifest which receives network change notifications and make a local broadcast each time the network connectivity is changed, that BroadcastReceiver uses the isInternetConnected() method and it also shown above.

The real beauty though is in the BroadcastReceiver that we are attaching in the NetworkHelper fragment and which puts up a dialog every time the internet connection is lost, notify the user that the internet connection has been lost or is required for this screen. Not only is the NetworkHelper Fragment acting as a Fragment to display the dialog every time internet connectivity is lost, it has also acting as a helper class holding methods related to checking internet connectivity.

Headless Fragment to request runtime permissions

As an example, we will request camera and microphone permissions. You will notice that the code below uses a callback strategy for the permissions. That is, the Activity which is attaching the CameraMicPermissionHelper Fragment, also has to implement CameraMicPermissionCallback. The Fragment does little else other than hold the logic for requesting the permission, if the permission has already been granted or if the permission, or the permission was successfully or unsuccessfully granted, the headless Fragment will simply notify the Activity which implement the callback.

It is recommended that if a permission is rejected, that you remember that a permission was denied and don’t keep requesting it, as the use case for an app may vary, I’ve created methods which you can use to set a permission as denied as and when you choose.

Also, for the code below [gist link], I’m using a slightly modified version of PermissionUtils that was provided by Google in it’s sample app. You can find it on my GitHub account at this link.

Using the Headless fragment is easy, simply attach it to your Activity as was shown earlier. When when you need to check permissions, simply call checkCameraMicPermissions() method. If you get a callback in the onCameraMicPermissionGranted() method, use the camera or else onCameraMicPermissionDenied() you can inform the user why you need the permission and ask that they try again. Do note that, if you do show any message in the onCameraMicPermissionDenied() method, do not automatically retry asking for the permission. If the user clicks “Do not ask again” when denying the permission, your app will enter an infinite loop.

Conclusion

Now that we have our Fragments, we can add them to our Activities as needed to get the functionality we want. Further, based on a users action you can attach a headless fragment to get functionality rather than have it attached all the time. You can even have a collection of functionality that you can add and remove depending on your needs for a particular screen and lastly, if you are careful, you can write these Fragments in a way that means you can reuse them in other projects with almost no change.

For more great stuff on Android development, please follow me on Medium and also feel free to follow me on LinkedIn, Google+ or Twitter.

--

--

Ali Muzaffar

A software engineer, an Android, and a ray of hope for your darkest code. Residing in Sydney.