onExitedRegion not being triggered

Hello,

I am in the process of adding beacon monitoring to an existing Android application. I have downloaded the sample monitoring app from cloud.estimote.com and everything seems to work as expected on my test device. However, I am having difficulties when integrating that code with my existing android application. Specifically I am able to get the onEnteredRegion callback to trigger reliably and show me a notification, but I am unable to get onExitedRegion to ever trigger. I am using a single beacon with “flip to sleep” enabled. When viewing the logs I can see the estimote sdk showing that monitoring has registered the exit since it prints the following to the logs

D/estimote( 3066): exited
D/estimote( 3066): exited
D/estimote( 3066): exited

but my callback is never triggered. My BeaconManager is configured as follows

    beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
        @Override
        public void onExitedRegion(Region region) {
            System.out.println("estimote - onExitedRegion: " + region.getIdentifier());
            String message = exitMessages.get(region.getIdentifier());
            System.out.println("estimote - onExitedRegion: " + message);
            if (message != null) {
                showNotification(message);
            }
        }
        @Override
        public void onEnteredRegion(Region region, List<Beacon> list) {
            System.out.println("estimote - onEnteredRegion: " + region.getIdentifier());
            String message = enterMessages.get(region.getIdentifier());
            System.out.println("estimote - onEnteredRegion: " + message);
            if (message != null) {
                showNotification(message);
            }
        }
    });

As far as I know I am using the newest SDK from github. Any ideas?

Can you provide some more information about device you are using and it’s Android version?
What is the exact version of SDK you are using? We are releasing quite often, so this is important information.
Can you provide more logs? Can you also provide code where you initialize BeaconManager, construct region object and start monitoring. Are you doing this in Activity or in Application class? (We advise to start monitoring in onCreate method of Application class).
Are you using SecureUUID? If so, are you using SecureRegion to monitor it?
Applications created from templates are using old SDK (0.9.4), could try to update them to 0.10.1 and try again?
onEnterRegion can happen almost immediately after beacon starts advertising, however onExitRegion may take some time. You may try to adjust that by decreasing wait period to 0, and scan peroid to 1s using BeaconManager#setBackgroundScanPeriod method.

Thanks for the response. Here are some extra details:

Can you provide some more information about device you are using and it's Android version?

I am using a HTC m8 with Android version 4.4.4.

What is the exact version of SDK you are using?

I have been testing with 0.10.1.

Can you also provide code where you initialize BeaconManager, construct region object and start monitoring. 

My code is derived from the sample app I downloaded from cloud.estimote.com. I have a BeaconNotificationsManager which contains a BeaconManager

package *REMOVED*;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.estimote.sdk.Beacon;
import com.estimote.sdk.BeaconManager;
import com.estimote.sdk.Region;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class BeaconNotificationsManager {

    private static final String TAG = "Proximity Test";
    public BeaconManager beaconManager;

    private List<Region> regionsToMonitor = new ArrayList();
    private HashMap<String, String> enterMessages = new HashMap();
    private HashMap<String, String> exitMessages = new HashMap();
    private Context context;
    private int notificationID = 0;

    public BeaconNotificationsManager(Context context) {
        this.context = context;
        beaconManager = new BeaconManager(context);
        beaconManager.setBackgroundScanPeriod(5000, 100);
        beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
            @Override
            public void onExitedRegion(Region region) {
                 System.out.println("estimote - onExitedRegion: " + region.getIdentifier());
                String message = exitMessages.get(region.getIdentifier());
                System.out.println("estimote - onExitedRegion: " + message);
                if (message != null) {
                    showNotification(message);
                }
            }
            @Override
            public void onEnteredRegion(Region region, List<Beacon> list) {
                System.out.println("estimote - onEnteredRegion: " + region.getIdentifier());
                String message = enterMessages.get(region.getIdentifier());
                System.out.println("estimote - onEnteredRegion: " + message);
                if (message != null) {
                    showNotification(message);
                }
            }
        });
    }

    public void addNotification(BeaconID beaconID, String enterMessage, String exitMessage) {
        Region region = beaconID.toBeaconRegion();
        enterMessages.put(region.getIdentifier(), enterMessage);
        exitMessages.put(region.getIdentifier(), exitMessage);
        regionsToMonitor.add(region);
    }

    public void startMonitoring() {
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                for (Region region : regionsToMonitor) {
	        beaconManager.stopMonitoring(region);
                    beaconManager.startMonitoring(region);
                }
            }
        });
    }

    private void showNotification(String message) {
        Intent resultIntent = new Intent(context, com.bredir.boopsie.cerritos.Boopsie.class);
        PendingIntent resultPendingIntent = PendingIntent.getActivity(
                context, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
                .setSmallIcon(android.R.drawable.ic_dialog_info)
                .setContentTitle("Region Test")
                .setContentText(message)
                .setDefaults(NotificationCompat.DEFAULT_ALL)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setContentIntent(resultPendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(notificationID++, builder.build());
    }
}

My Application then contains a BeaconNotificationsManager with the following initialization code

private boolean beaconNotificationsEnabled = false;
public BeaconNotificationsManager beaconNotificationsManager;

public void enableBeaconNotifications() {
        if (beaconNotificationsEnabled) { return; }
        beaconNotificationsManager = new BeaconNotificationsManager(this);
        beaconNotificationsManager.addNotification(
                new BeaconID("B9407F30-F5F8-466E-AFF9-25556B57FE6D", REMOVED, REMOVED),
                "Hello",
                "Goodbye"
        );
        beaconNotificationsEnabled = true;
        beaconNotificationsManager.startMonitoring();
    }

enableBeaconNotifications is called in the onCreate method of my main Activity.

Are you using SecureUUID? If so, are you using SecureRegion to monitor it?

No, I am not currently using SecureUUID.

Thanks again for the response.

I just switched my project over to a much older version of the SDK (0.8.1 - https://github.com/Estimote/Android-SDK/releases/tag/0.8.1) and with a few small API changes my code now shows onEnter and onExit messages as I expected. Have there been changes since then that would cause this behavior?

Since that version many things have changed. Most importantly a support for Android 5.0 Bluetooth LE scanning API was introduced, many bugs were fixed.
We are trying to recreate problem on HTC One with Android 4.4.3 but onExit callbacks are invoked. Interestingly we noticed that if there is too many notifications from one application, Android stops displaying new ones - maybe this is source of your problem?.
Can you verify if your code works on a different phone? Android 5.0 or later are recommended since they usually have much more stable Bluetooth stack.
Other thing to you can do is to change scan period to:

beaconManager.setBackgroundScanPeriod(1000, 0);

This way SDK will be scanning constantly. Remember to adjust it back when releasing production app.