Android - Managing Multiple BroadcastReceivers

When I was developing the Presently Android client I ran into an interesting problem. If a user is in the main timeline activity and a new message comes in, the active timeline just needs to update with the new message. However, if the user is in another activity stream, (like viewing @ replies or DM’s for example) and a new message comes in to the main stream the application should not only update the main stream but should also show the user a notification so they can be aware that new messages are coming into another activity.

In this post I will show you how I solved this problem.

There is a background service to pull new messages from the server. When the service receives a new message, a broadcast will be sent:

public class RefreshService extends Service {
    public void refreshTimeline() {
    //build the intent with new messages
    sendBroadcast(intent);
    }
}

Then, we have a BroadcastReceiver in TimelineActivity to receive the broadcast.

public class TimelineActivity {
    private RefreshTimelineReceiver refreshReceiver;
    
    public void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(RefreshService.REFRESH_TIMELINE);
        refreshReceiver = new RefreshTimelineReceiver();
        registerReceiver(refreshReceiver, filter);
    }
    
    public void onPause() {
        super.onPause();
        unregisterReceiver(refreshReceiver);
    }
    
    public class RefreshTimelineReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            showNewMessages();
            showNotification();
        }
    }
}

Now, when new messages come in the user can see the messages update to listview and get a notification in the status bar. But there is a small problem: it only works in TimelineActivity, because when the user opens a new activity or presses the Home button, the BroadcastReceiver is unregistered in the onPause() method.

So I tried to put the register/unregister operation in the onCreate()/onDestroy() methods. This fixed the problem of new messages and notifications not showing in other activities. But then there was another problem: in TimelineActivity, the user receives an additional and unnecessary notification. So I set out to fix this particular problem.

The first question I asked myself was, “Can I only use one BroadcastReceiver?” The answer was “No!” So, I used two BroadcastReceiver(s) to fix this problem.

public class RefreshService extends Service {
    public void refreshTimeline() {
    //build the intent with new messages
    this.sendOrderedBroadcast(intent, null);
    }
}
public class TimelineActivity {
    private RefreshTimelineReceiver refreshReceiver;
    private RefreshTimelineAndNotifyReceiver refreshAndNotifyReceiver;
    
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    IntentFilter filter = new IntentFilter(RefreshService.REFRESH_TIMELINE);
        filter.setPriority(FILTER_LOW_PRIORITY);
        refreshAndNotifyReceiver = new RefreshTimelineAndNotifyReceiver();
        registerReceiver(refreshAndNotifyReceiver, filter);
    }
    
    public void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(RefreshService.REFRESH_TIMELINE);
        filter.setPriority(FILTER_HIGH_PRIORITY);
        refreshReceiver = new RefreshTimelineReceiver();
        registerReceiver(refreshReceiver, filter);
    }
    
    public void onPause() {
        super.onPause();
        unregisterReceiver(refreshReceiver);
    }
    
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(refreshAndNotifyReceiver);
    }
    
    public class RefreshTimelineReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            showNewMessages();
            this.abortBroadcast();
        }
    }
    
    public class RefreshTimelineAndNotifyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            showNewMessages();
            showNotification();           
        }
    }
}

In this code there are some key points I want to outline:

And this is how I solved the problem of notifying a Presently Android user of new incoming messages to the main activity if they are active in a separate activity stream. Hopefully this might help someone else out who might be working through a similar problem!