How to check if Receiver is registered in Android?
Solution 1
I am not sure the API provides directly an API, if you consider this thread:
I was wondering the same thing.
In my case I have aBroadcastReceiver
implementation that callsContext#unregisterReceiver(BroadcastReceiver)
passing itself as the argument after handling the Intent that it receives.
There is a small chance that the receiver'sonReceive(Context, Intent)
method is called more than once, since it is registered with multipleIntentFilters
, creating the potential for anIllegalArgumentException
being thrown fromContext#unregisterReceiver(BroadcastReceiver)
.In my case, I can store a private synchronized member to check before calling
Context#unregisterReceiver(BroadcastReceiver)
, but it would be much cleaner if the API provided a check method.
Solution 2
There is no API function to check if a receiver is registered. The workaround is to put your code in a try catch block as done below.
try {
//Register or UnRegister your broadcast receiver here
} catch(IllegalArgumentException e) {
e.printStackTrace();
}
Solution 3
simplest solution
in receiver:
public class MyReceiver extends BroadcastReceiver {
public boolean isRegistered;
/**
* register receiver
* @param context - Context
* @param filter - Intent Filter
* @return see Context.registerReceiver(BroadcastReceiver,IntentFilter)
*/
public Intent register(Context context, IntentFilter filter) {
try {
// ceph3us note:
// here I propose to create
// a isRegistered(Contex) method
// as you can register receiver on different context
// so you need to match against the same one :)
// example by storing a list of weak references
// see LoadedApk.class - receiver dispatcher
// its and ArrayMap there for example
return !isRegistered
? context.registerReceiver(this, filter)
: null;
} finally {
isRegistered = true;
}
}
/**
* unregister received
* @param context - context
* @return true if was registered else false
*/
public boolean unregister(Context context) {
// additional work match on context before unregister
// eg store weak ref in register then compare in unregister
// if match same instance
return isRegistered
&& unregisterInternal(context);
}
private boolean unregisterInternal(Context context) {
context.unregisterReceiver(this);
isRegistered = false;
return true;
}
// rest implementation here
// or make this an abstract class as template :)
...
}
in code:
MyReceiver myReceiver = new MyReceiver();
myReceiver.register(Context, IntentFilter); // register
myReceiver.unregister(Context); // unregister
ad 1
-- in reply to:
This really isn't that elegant because you have to remember to set the isRegistered flag after you register. – Stealth Rabbi
-- "more ellegant way" added method in receiver to register and set flag
this won't work If you restart the device or if your app got killed by OS. – amin 6 hours ago
@amin - see lifetime of in code (not system registered by manifest entry) registered receiver :)
Solution 4
I am using this solution
public class ReceiverManager {
private WeakReference<Context> cReference;
private static List<BroadcastReceiver> receivers = new ArrayList<BroadcastReceiver>();
private static ReceiverManager ref;
private ReceiverManager(Context context) {
cReference = new WeakReference<>(context);
}
public static synchronized ReceiverManager init(Context context) {
if (ref == null) ref = new ReceiverManager(context);
return ref;
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter intentFilter) {
receivers.add(receiver);
Intent intent = cReference.get().registerReceiver(receiver, intentFilter);
Log.i(getClass().getSimpleName(), "registered receiver: " + receiver + " with filter: " + intentFilter);
Log.i(getClass().getSimpleName(), "receiver Intent: " + intent);
return intent;
}
public boolean isReceiverRegistered(BroadcastReceiver receiver) {
boolean registered = receivers.contains(receiver);
Log.i(getClass().getSimpleName(), "is receiver " + receiver + " registered? " + registered);
return registered;
}
public void unregisterReceiver(BroadcastReceiver receiver) {
if (isReceiverRegistered(receiver)) {
receivers.remove(receiver);
cReference.get().unregisterReceiver(receiver);
Log.i(getClass().getSimpleName(), "unregistered receiver: " + receiver);
}
}
}
Solution 5
You have several options
You can put a flag into your class or activity. Put a boolean variable into your class and look at this flag to know if you have the Receiver registered.
Create a class that extends the Receiver and there you can use:
Singleton pattern for only have one instance of this class in your project.
Implement the methods for know if the Receiver is register.
Related videos on Youtube
Mikey
Android Application Developer, Mobile Application Design and analysis.
Updated on March 04, 2021Comments
-
Mikey over 3 years
I need to check if my registered receiver is still registered if not how do i check it any methods?
-
Shirish Herwade almost 8 years
-
-
JPM over 12 yearsFunny thing is that doesn't catch the error for this call to BroadcastReceiver for registerReceiver(mReceiver, filter1);
-
Admin over 11 years@JPM Yes it is. I was going to store an instance of my receiver and check to unregister it if it is not
null
. But as you pointed out, I'm going withtry catch
. Ridiculous. -
slinden77 about 11 yearshaha, I find them convenient :) Quicker overview on the format and where stuff starts and ends :) eacht to his own I guess
-
slinden77 about 11 yearsmmm, looking into that as per your comment, looking good! Ofcourse it screwed up my Eclipse workspace, but not much is needed for that :)
-
Martin Marconcini about 11 yearsOh, switch to IntelliJ, once you get used to it, Eclipse feels really old ;) On the plus side, the new Android Studio is just an IntelliJ with a few add-ons so if you're used to Intellij, Android Studio will make you feel right at home.
-
hB0 almost 11 yearsI have done the same but my receiver is the AppWidgetProvider and I want to receive SCREEN_ON_OFF messages - but onDisabled() when I unregisterReceiver(this); - it throws exception.
-
Gaeburider about 10 yearscombined first and second option, a flag in the receiver class, works greatly
-
DustinB almost 10 yearsHow/where does this throw an NPE?
-
domenukk over 9 yearsIt does not throw any errors when it's unsuccessful, actually. Sadly.
-
portfoliobuilder almost 9 yearsActually, it does throw an IllegalArgumentException
-
MarkJoel60 over 8 yearsThis really is an elegant solution. FWIW, in Android Studio, when I try to extend BroadcastReceiver, it complains and wants an override of onReceive. Fortunately, in my case, I was needing to extend ScreenReceiver, which operates exactly the way ceph3us describes here.
-
Stealth Rabbi over 8 yearsThis really isn't that elegant because you have to remember to set the isRegistered flag after you register.
-
Stealth Rabbi over 8 yearsYes, although you can remove this line from your "in code" section. myReceiver.isRegistered = true;
-
Denys Vitali over 8 yearsDownvote to Android for not creating an API for that. +1 to you for providing a working solution :)
-
slinden77 almost 8 years@MartínMarconcini well finally I was forced to switch to IntelliJ. I like it very much, but I despise the fact it's impossible to work in 2 projects simultaniously.
-
Martin Marconcini almost 8 yearsWelcome to the dark side ;) I have three Android Studio open right now with 3 different projects… not sure what your multiple-project problem is, but I can assure you that it works with multiple projects. :)
-
DAVIDBALAS1 almost 8 yearsWhat's better? using this or using a boolean variable as a flag?
-
AlbertMarkovski over 7 years@DAVIDBALAS1 I think that it may depend on the use case. I've elected to use a boolean, because that variable is useful for me again.
-
HendraWD over 7 yearsI will go with this instead of boolean variable as a flag, because i don't want to make 1 more variable on my class and maintain the state of the flag. Especially if my class is already big
-
TapanHP over 7 yearscan you give me a code example as i m not getting what u r exactly doing...would b great help @chemalarrea
-
York Yang almost 7 yearsshouldn't this be an abstract class? extending BroadcastReceiver requires you to implement the onReceive method.
-
ceph3us almost 7 yearsdown for leaked context (have you heard about weak references) ?
-
ceph3us almost 7 years@YorkYang added info in class at the bottom
-
Vivek Barai over 6 yearsOrdered Broadcast is completely another thing have a look at this link
-
ocramot about 6 yearsI will go with this instead of boolean variable as a flag, because if the registering is still hanging for any reason and the flag has not been set to true yet, then the unregistering would still raise the exception
-
exploitr almost 6 yearsIt's from the TelephonyManager class? @slinden77
-
exploitr almost 6 yearsAlso, your code pushes memory leaks. Try no to place context classes in static fields. Use WeakReference. Anyway +1
-
KenIchi almost 6 yearsI posted a similar concern of querying the MediaCodec's state. Please check if it's of interest: stackoverflow.com/q/51780322/1562087
-
Amin Pinjari about 5 yearsthis won't work If you restart the device or if your app got killed by OS.
-
Steve Kamau almost 4 yearsI have made an edit for holding the content within a WeakReference.
-
DADi590 almost 3 yearsBut how can you be sure the exception will be thrown if it's not on the method signature nor anywhere? (At least I don't see anywhere mentioning the exception will be thrown.)
-
ONE over 2 yearsThis does not work (tested to verify). The receiver.isOrderedBroadcast() condition is not a stand-in for determining if a BroadcastReceiver is registered. It returns false even for legitimately registered BroadcastReceivers (again, tested it to verify). There is as yet no way in the API to determine if a BroadcastReceiver is registered. Just a minor oversight by the Android team.
-
Kishan Solanki about 2 yearsThis is not working. Have you tested this before posting here? Share source URL