7

I'm having some problems unregistering a BroadcastReceiver. I'm first registering it but then when I want to unregister it by using unregisterReceiver(); command gives me tons of errors. The error says that I've not registered my BroadcastReceiver.

Code:

public class Receiver extends BroadcastReceiver implements Variables {

    CheckConexion cc;

    @Override
    public void onReceive(Context contxt, Intent intent) {

        // Cuando hay un evento, lo diferenciamos y hacemos una acción.

        if (intent.getAction().equals(SMS_RECEIVED)) {
            Sms sms = new Sms(null, contxt);
            sms.uploadNewSms(intent);
        } else if (intent.getAction().equals(Intent.ACTION_BATTERY_LOW)) {
            // st.batterylow(contxt);
        } else if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
            // st.power(1, contxt);
        } else if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
            // st.power(0, contxt);
        } else if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)
                || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)
                || intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
            Database db = new Database(contxt);
            if (db.open().Preferences(4)) {
                Uri data = intent.getData();
                new ListApps(contxt).import_app(intent, contxt, data,
                        intent.getAction());
            }
            db.close();
        } else if (intent.getAction().equals(
                ConnectivityManager.CONNECTIVITY_ACTION)) {
            cc = new CheckConexion(contxt);
            if (cc.isOnline()) {

                /*Database db = new Database(contxt);
                db.open();
                if (db.move() == 1) {
                    new UploadOffline(contxt);
                }
                db.close();*/

            }
        }

    }

    public void register(Context c) {
        Receiver r = new Receiver();
        IntentFilter i = new IntentFilter();
        i.addAction(SMS_RECEIVED);
        i.addAction(Intent.ACTION_BATTERY_LOW);
        i.addAction(Intent.ACTION_POWER_CONNECTED);
        i.addAction(Intent.ACTION_POWER_DISCONNECTED);
        i.addAction(Intent.ACTION_CALL_BUTTON);
        i.addAction(Intent.ACTION_CAMERA_BUTTON);
        i.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        c.registerReceiver(r, i);
        IntentFilter apps = new IntentFilter();
        apps.addAction(Intent.ACTION_PACKAGE_ADDED);
        apps.addAction(Intent.ACTION_PACKAGE_CHANGED);
        apps.addAction(Intent.ACTION_PACKAGE_REMOVED);
        apps.addDataScheme("package");
        c.registerReceiver(r, apps);
    }

    public void unregister(Context c) {
        BroadcastReceiver r = new Receiver();
        if (r != null) {
            c.unregisterReceiver(r);
        }
    }
}
nullability
  • 10,545
  • 3
  • 45
  • 63
Marc Ortiz
  • 2,242
  • 5
  • 27
  • 46

4 Answers4

7

First of all,

Use this to work with the object of the class Reciever

remove all r objects, don't call constructors in the extending class.

Then:

Define

boolean isRegistered = false;

In your register method:

c.registerReceiver(this);
isRegistered = true;

In your unregister method:

if (isRegistered) {
    c.unregisterReceiver(this);
    isRegistered = false;
}

Then in your activity use instance of the class Reciver.

Hope, it was helpful!

JunR
  • 202
  • 1
  • 6
  • This solution should work. However, the need to have a member variable for every registered receiver is not always convenient. If you want to avoid using member variables for every receiver, you can take a look at my solution below. It is basically to use a try catch block. – jfmg Jul 07 '15 at 18:13
  • To avoid keeping another variable, declare an inner class that subclasses `BroadcastReceiver`. Construct a new one when registering, and `null` it just after unregistering. – gladed Apr 14 '17 at 19:04
6

The best solution is to put the unregisterReceiver method into a try catch block.

try {
    this.unregisterReceiver(myReceiver);
}
catch (final Exception exception) {
    // The receiver was not registered.
    // There is nothing to do in that case.
    // Everything is fine.
}

Unfortunately, there is no specific exception thrown when unregisterReceiver fails, so you got to use Exception. Also, there is unfortunately no method like isReceiverRegistered(BroadcastReceiver receiver), which in my opinion would be an enhancement to the Android API.

Besides, it won't hurt to take a look at ReceiverLifecycle

jfmg
  • 2,626
  • 1
  • 24
  • 32
4

You cannot unregister a new instance of broadcast Receiver. You will need to use the same instance of BroadcastReciever which has been registered.

So use

 c.registerReceiver(this, apps);

and

 c.unregisterReceiver(this);
nandeesh
  • 24,740
  • 6
  • 69
  • 79
0

In unregister method, you are creating a new BroadcastReceiver instance and unregistering that. Instead make the instance in register method global and call

if (r != null) {
        c.unregisterReceiver(r);
        r = null;
 }

in unregister method.

user936414
  • 7,574
  • 3
  • 30
  • 29
  • This can throw an exception when your variable `r` is not null and not registered. – jfmg Apr 05 '17 at 18:04
  • 1
    If this is the only place where unregisterReceiver() is called, then if it throws its an Android defect. – gladed Apr 14 '17 at 19:08