Be Polite with Android Broadcast Receiver

Performance, or ‘perf’ as all the cool kids now say, is a big topic in the Android world.  No matter how sleek your UX / UI, if your app is laggy or crashy, users will not be happy. Unfortunately, there is no silver bullet for performance; there is no one line code fix, and no library you can import to get good performance.  A high performing application is the result of many incremental software design and implementation decisions. On top of that, you have to be constantly monitoring your app’s performance. Any refactoring or new feature could result in a drop in performance. In other words, its not exactly easy.

Recently I refactored my Lunch In Receiver code a little. It was a simple refactor that could help performance, so I figured I’d share it!

An Android Broadcast Receiver is a background entity that receives information about the surrounding environment it has been designated to care about.  By default receivers are “always on,” meaning they are always listening in for their designated event to occur.  This means a user could download your app but never open it, yet a Broadcast Receiver in your app is firing away.

For many apps, a Broadcast Receiver’s actions might not make sense if the user hasn’t at least opened the app and performed some tasks. This was the case for the LunchOutDetectionReceiver in Lunch In.

This Broadcast Receiver listens for a change in wifi state to detect if you have left your office by moving off the office wifi signal.  The actual receiver fires if there is any change in wifi state, and then the code within the receiver checks to see if your change was related to your work wifi or not. Since receivers are “on” as soon as the app is installed, the receiver could be firing and checking against the user’s work wifi, before the user has even registered their work wifi in the apps settings. 🙁 This is wasteful!

Luckily, you can disable your Receiver until it makes sense to turn it on. The solution is easy and has 2 parts:

1. Manifest

First step is explicitly disable your receiver. You do this in AndroidManifest.xml when you define the receiver:

<receiver android:name=".receiver.LunchOutDetectionReceiver" android:enabled="false">

2. Java

Next step is to figure our where in the logic of your app it makes sense to turn the receiver on.  For our app, it doesn’t make sense to have the receiver on until the user has actually registered their work wifi.  So I turn the receiver on in our settings code if the user is adding their work wifi for the first time:

// Only turn on the receiver if its the user's first time setting it up
if( (originalWorkWifiId == null) || (originalWorkWifiId.isEmpty()) ){
    
    PackageManager pm  = getActivity().getPackageManager();

    ComponentName componentName = new ComponentName( getActivity(), LunchOutDetectionReceiver.class );

    pm.setComponentEnabledSetting( componentName,PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                                           PackageManager.DONT_KILL_APP);
}

 

You can take a look at the code diff for my pull request on this issue here.

I invite you to take a look at any Broadcast Receiver you have in your application. Scrutinize its functionality, and see if you can hold off on enabling it until it absolutely makes sense!

This entry was posted in Android. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *