How to check if Receiver is registered in Android?

150,270

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 a BroadcastReceiver implementation that calls Context#unregisterReceiver(BroadcastReceiver) passing itself as the argument after handling the Intent that it receives.
There is a small chance that the receiver's onReceive(Context, Intent) method is called more than once, since it is registered with multiple IntentFilters, creating the potential for an IllegalArgumentException being thrown from Context#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

  1. 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.

  2. Create a class that extends the Receiver and there you can use:

    1. Singleton pattern for only have one instance of this class in your project.

    2. Implement the methods for know if the Receiver is register.

Share:
150,270

Related videos on Youtube

Mikey
Author by

Mikey

Android Application Developer, Mobile Application Design and analysis.

Updated on March 04, 2021

Comments

  • Mikey
    Mikey over 3 years

    I need to check if my registered receiver is still registered if not how do i check it any methods?

  • JPM
    JPM over 12 years
    Funny thing is that doesn't catch the error for this call to BroadcastReceiver for registerReceiver(mReceiver, filter1);
  • Admin
    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 with try catch. Ridiculous.
  • slinden77
    slinden77 about 11 years
    haha, I find them convenient :) Quicker overview on the format and where stuff starts and ends :) eacht to his own I guess
  • slinden77
    slinden77 about 11 years
    mmm, 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
    Martin Marconcini about 11 years
    Oh, 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
    hB0 almost 11 years
    I 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
    Gaeburider about 10 years
    combined first and second option, a flag in the receiver class, works greatly
  • DustinB
    DustinB almost 10 years
    How/where does this throw an NPE?
  • domenukk
    domenukk over 9 years
    It does not throw any errors when it's unsuccessful, actually. Sadly.
  • portfoliobuilder
    portfoliobuilder almost 9 years
    Actually, it does throw an IllegalArgumentException
  • MarkJoel60
    MarkJoel60 over 8 years
    This 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
    Stealth Rabbi over 8 years
    This really isn't that elegant because you have to remember to set the isRegistered flag after you register.
  • Stealth Rabbi
    Stealth Rabbi over 8 years
    Yes, although you can remove this line from your "in code" section. myReceiver.isRegistered = true;
  • Denys Vitali
    Denys Vitali over 8 years
    Downvote to Android for not creating an API for that. +1 to you for providing a working solution :)
  • slinden77
    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
    Martin Marconcini almost 8 years
    Welcome 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
    DAVIDBALAS1 almost 8 years
    What's better? using this or using a boolean variable as a flag?
  • AlbertMarkovski
    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
    HendraWD over 7 years
    I 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
    TapanHP over 7 years
    can you give me a code example as i m not getting what u r exactly doing...would b great help @chemalarrea
  • York Yang
    York Yang almost 7 years
    shouldn't this be an abstract class? extending BroadcastReceiver requires you to implement the onReceive method.
  • ceph3us
    ceph3us almost 7 years
    down for leaked context (have you heard about weak references) ?
  • ceph3us
    ceph3us almost 7 years
    @YorkYang added info in class at the bottom
  • Vivek Barai
    Vivek Barai over 6 years
    Ordered Broadcast is completely another thing have a look at this link
  • ocramot
    ocramot about 6 years
    I 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
    exploitr almost 6 years
    It's from the TelephonyManager class? @slinden77
  • exploitr
    exploitr almost 6 years
    Also, your code pushes memory leaks. Try no to place context classes in static fields. Use WeakReference. Anyway +1
  • KenIchi
    KenIchi almost 6 years
    I posted a similar concern of querying the MediaCodec's state. Please check if it's of interest: stackoverflow.com/q/51780322/1562087
  • Amin Pinjari
    Amin Pinjari about 5 years
    this won't work If you restart the device or if your app got killed by OS.
  • Steve Kamau
    Steve Kamau almost 4 years
    I have made an edit for holding the content within a WeakReference.
  • DADi590
    DADi590 almost 3 years
    But 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
    ONE over 2 years
    This 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
    Kishan Solanki about 2 years
    This is not working. Have you tested this before posting here? Share source URL