2

I have implemented a BroadcastReceiver (called ProximityIntentReceiver) in my Android app, but i have some annoying problems. In the onCreate() method of my MainActivity I call this function:

addProximityAlert():

private ProximityIntentReceiver proximityIntentReceiver;
private void addProximityAlert() {
    pendingIntentList = new HashMap<Integer, PendingIntent>();
    double latitude = 37.567072;
    double longitude = 14.273046;
    Intent intent = new Intent(PROX_ALERT_INTENT);
    PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
    locationManager.addProximityAlert(
            latitude, // the latitude of the central point of the alert region
            longitude, // the longitude of the central point of the alert region
            POINT_RADIUS, // the radius of the central point of the alert region, in meters
            PROX_ALERT_EXPIRATION, // time for this proximity alert, in milliseconds, or -1 to indicate no                           expiration
            proximityIntent // will be used to generate an Intent to fire when entry to or exit from the alert region is detected
    );
    pendingIntentList.put(1, proximityIntent);
    proximityIntentReceiver = new ProximityIntentReceiver();
    registerReceiver(proximityIntentReceiver, filter);
    Toast.makeText(getApplicationContext(),"Alert Added",Toast.LENGTH_SHORT).show();
}

This is, instead, the onDestroy of my MainActivity:

onDestroy():

@Override
public void onDestroy() {
    super.onDestroy();
    accessTokenTracker.stopTracking();
    if(proximityIntentReceiver!=null) {
        unregisterReceiver(proximityIntentReceiver);
        removeProximityAlert();

    }
}

removeProximityAlert():

private HashMap<Integer, PendingIntent> pendingIntentList;
private void removeProximityAlert () {

    Iterator<Map.Entry<Integer, PendingIntent>> iterator = pendingIntentList.entrySet().iterator() ;
    while(iterator.hasNext()){
        Map.Entry<Integer, PendingIntent> pendingIntentMap = iterator.next();
        locationManager.removeProximityAlert(pendingIntentMap.getValue());
    }
}

Now if i change something on my BroadcastReceiver or in my addProximityAlert(), changes remain the same until I reboot the device. Why? I thought that by calling the unregisterReceiver() method was sufficient to remove the instance of the BroadcastReceiver...

What should I add to my code?

shkschneider
  • 17,833
  • 13
  • 59
  • 112
Francesco Lombardo
  • 335
  • 1
  • 4
  • 15
  • > _Now if i change something on my BroadcastReceiver or in my addProximityAlert, changes remain the same until i reboot the device._ Specifically, what are you changing and what do you expect to see? – user3452758 May 04 '15 at 11:43
  • For example if i change the POINT_RADIUS variable or something else... – Francesco Lombardo May 04 '15 at 11:58

2 Answers2

2

A BroadcastReceiver only exists during the execution of its onReceive() method. So, this evaluates to a throw-away instance every time the broadcast is fired/received. For dynamically registering/unregistering of BroadcastReceivers, you have to remember the instance of your receiver in onPause() to register it again during onResume().

@Override
protected void onPause() {
    unregisterReceiver(mReceiver);
    super.onPause();
}

For an Activity:

In order to register your BroadcastReceiver from within your app, first, remove the <receiver> tag from your AndroidManifest.xml file. Then, call registerReceiver(BroadcastReceiver receiver, IntentFilter filter) in your onResume(). Use unregisterReceiver(BroadcastReceiver receiver) in your onPause() to unregister the BroadcastReceiver.

For a Service:

Remove the receiver tag from the manifest file. You can then register your BroadcastReceiver with the same method in the onCreate() and unregister in the onDestroy().

Took Reference From: 1: Unregister broadcast receiver 2: unregister receiver

You can check here, which gives you more details about the working of BroadcastReceivers.

Still not your problem is solved, please let me know.

Community
  • 1
  • 1
RIJO RV
  • 806
  • 6
  • 18
  • So i have to remove the unregisterReceiver method from onDestroy and calling it in onPause? And i have to remove the registerReceiver from my addProximityAlert? – Francesco Lombardo May 04 '15 at 12:04
  • you should unregister it from onPause() method. – RIJO RV May 04 '15 at 12:05
  • Sorry, I accidentally pressed the Enter key before finishing the comment – Francesco Lombardo May 04 '15 at 12:09
  • its ok. You should need to unregister receiver form onPause() and need to register receiver from onResume(). – RIJO RV May 04 '15 at 12:14
  • I made these changes but the problem persist... If you restart the phone the receiver is called, otherwise nothing happens – Francesco Lombardo May 04 '15 at 12:25
  • What happens if you have something like an importer object that's created in the onReceive() method, then importer.execute() is applied in a separate thread? Will onReceive() garbage collect the importer mid execution? – user2892437 Mar 27 '17 at 19:36
1

I suspect your constraints (POINT_RADIUS etc) are not being updated because you're retrieving your pending intent with flags '0':

PendingIntent.getBroadcast(this, 0, intent, 0);

LocationManager.addProximityAlert() takes the pending intent you give it and sets up a recurring alarm using the intent it contains. If you subsequently call addProximityAlert() with a PendingIntent that matches the previous one (according to Intent.filterEquals()), the alarm won't get updated, and your new constraints will not take effect.

To fix, you need to set the right flag so that the pending intent replaces the previous one.

PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

The flags are documented here (incidentally, I think '0' is undefined behaviour): http://developer.android.com/reference/android/app/PendingIntent.html

NB, if FLAG_UPDATE_CURRENT does not work, you may need FLAG_CANCEL_CURRENT instead.

user3452758
  • 638
  • 1
  • 7
  • 15