Skip to content

Instantly share code, notes, and snippets.

@curioustechizen
Last active June 11, 2020 18:15
Show Gist options
  • Save curioustechizen/8728945 to your computer and use it in GitHub Desktop.
Save curioustechizen/8728945 to your computer and use it in GitHub Desktop.
Tiny utility class that helps avoid book-keeping code when dealing with registering and unregistering BroadcastReceivers. Hopefully, this will help you get rid of "Activity has leaked IntentReceiver that was originally registered here" messages without resorting to using boolean flags to keep track of your BroadcastReceivers.
package com.github.curioustechizen.safereg;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.util.ArrayMap;
/**
* Helper class to keep track of what {@code BroadcastReceiver}s have been
* registered for this context. Requests for registering a new receiver will act
* only if the not already registered. Similarly, requests for unregistering a
* receiver will act only if the register is already registered.
*
* @author Kiran Rao
*
*/
public class ReceiverRegistrar {
private Context mContext;
private ArrayMap<BroadcastReceiver, Intent> mReceiverMap;
/**
* Construct a new instance of the registrar.
*
* @param context
* The context that is used for registering the receiver
*/
public ReceiverRegistrar(Context context) {
mContext = context;
mReceiverMap = new ArrayMap<BroadcastReceiver, Intent>();
}
/**
* Register a {@code BroadcastReceiver}. If the receiver is already
* registered then this method will simply return the {@code Intent}
* returned by the previous {@code registerReceiver} call.
*
* @see {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)}
* @param receiver
* The BroadcastReceiver to handle the broadcast
* @param filter
* The filter to select the broadcasts to be handled
* @return The first sticky intent found that matches filter, or null if
* there are none. If this receiver has already been registered,
* then the return value is the intent that was returned when the
* receiver was originally registered.
*/
public Intent safeRegisterReceiver(BroadcastReceiver receiver,
IntentFilter filter) {
if (!mReceiverMap.containsKey(receiver)) {
Intent intent = mContext.registerReceiver(receiver, filter);
mReceiverMap.put(receiver, intent);
return intent;
} else {
return mReceiverMap.get(receiver);
}
}
/**
* Unregister a {@code BroadcastReceiver}, if it hasn't been registered
* already.
*
* @param receiver
*/
public void safeUnregisterReceiver(BroadcastReceiver receiver) {
if (mReceiverMap.containsKey(receiver)) {
mContext.unregisterReceiver(receiver);
mReceiverMap.remove(receiver);
}
}
/**
* Unregister all {@code BroadcastReceiver}s registered with this context.
*/
public void safeUnregisterAllReceivers() {
for (BroadcastReceiver receiver : mReceiverMap.keySet()) {
safeUnregisterReceiver(receiver);
}
}
}
package com.github.curioustechizen.safereg;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.os.Bundle;
/*
* Naive implementation of registering and un-registering multiple BroadcastReceivers
* in an Activity using boolean flags to keep track of whether they have been registered.
*
* You probably want to use ReceiverRegistrar instead of this as demonstrated in SampleRecommendedActivity.java
*/
public class SampleNaiveActivity extends Activity {
private BroadcastReceiver mConnectivityReceiver, mBatteryReceiver;
private IntentFilter mConnectivityFilter, mBatteryFilter;
private boolean mRegisteredConnectivityReceiver,
mRegisteredBatteryReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* Initialize the BroadcastReceivers here Setup the IntentFilters here
*/
}
@Override
protected void onResume() {
super.onResume();
/*
* Register your receivers in onResume
*/
registerBatteryReceiver();
registerConnectivityReceiver();
}
private void onBatteryLow() {
/*
* Maybe when the battery goes low you want to unregister a few
* receivers?
*/
unregisterConnectivityReceiver();
}
@Override
protected void onPause() {
super.onPause();
/*
* In onPause, unregister all remaining registered receivers
*/
unregisterBatteryReceiver();
unregisterConnectivityReceiver();
}
private void registerBatteryReceiver() {
if (!mRegisteredBatteryReceiver) {
mRegisteredBatteryReceiver = true;
registerReceiver(mBatteryReceiver, mBatteryFilter);
}
}
private void unregisterBatteryReceiver() {
if (mRegisteredBatteryReceiver) {
mRegisteredBatteryReceiver = false;
unregisterReceiver(mBatteryReceiver);
}
}
private void registerConnectivityReceiver() {
if (!mRegisteredConnectivityReceiver) {
mRegisteredConnectivityReceiver = true;
registerReceiver(mConnectivityReceiver, mConnectivityFilter);
}
}
private void unregisterConnectivityReceiver() {
if (mRegisteredConnectivityReceiver) {
mRegisteredConnectivityReceiver = false;
unregisterReceiver(mConnectivityReceiver);
}
}
}
package com.github.curioustechizen.safereg;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.os.Bundle;
public class SampleRecommendedActivity extends Activity {
private BroadcastReceiver mConnectivityReceiver, mBatteryReceiver;
private IntentFilter mConnectivityFilter, mBatteryFilter;
private ReceiverRegistrar mReceiverRegistrar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* Initialize the BroadcastReceivers here and Setup the IntentFilters here
*/
mReceiverRegistrar = new ReceiverRegistrar(this);
}
@Override
protected void onResume() {
super.onResume();
/*
* Register your receivers in onResume
*/
mReceiverRegistrar.safeRegisterReceiver(mBatteryReceiver,
mBatteryFilter);
mReceiverRegistrar.safeRegisterReceiver(mConnectivityReceiver,
mConnectivityFilter);
}
private void onBatteryLow() {
/*
* Maybe when the battery goes low you want to unregister a few
* receivers?
*/
mReceiverRegistrar.safeUnregisterReceiver(mConnectivityReceiver);
}
@Override
protected void onPause() {
super.onPause();
/*
* In onPause, unregister all remaining registered receivers
*/
mReceiverRegistrar.safeUnregisterAllReceivers();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment