Scaning beacon when phone is sleeping

I implemented a service which is ranging proximity of the beacons in the background.
I set the following properties for scan:

beaconManager.setBackgroundScanPeriod(2000, 3000);
beaconManager.setForegroundScanPeriod(2000, 3000);
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);

Everything works fine at the beginning. After more than 1 hour, scan period become problematic. When i debug the application scan period increasing with time.(sometimes it can reach 30 minutes). I guess OS wants to save battery and increase the scan period. But what i need is fixed scan period. How can i achieve this?

I am using estimote sdk library. There was a Android AlarmManager usage for trigger next scan period. I think AlarmManager could be our problem. There is a note in docs as follow:

Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to “batch” alarms together across the entire system, minimizing the number of times the device needs to “wake up” and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.

How can I get fixed scan period?

What you are observing is so called device’s deep sleep. We do use AlarmManager to get phone our of deep sleep. We will be this week investigating this issue so stay tuned (follow Android SDK released on GitHub).

Have you considered using monitoring API? That is startMonitoring on BeaconManager.

Thanks for solution oriented approach.

My main goal is to find the closest beacon. I guess startRanging method is preferable than startMonitoring. I don’t mind entering region. I haven’t tried monitoring API yet. But if it’s a solution, i could try. Also i can try another ways of solutions depending on your advices.

I am looking forward to new sdk release. I hope this problem will be solved.

I checked to new version of SDK but i couldn’t see any news about this problem.
Could i take information about progress?

In v0.9.2 release we did tune monitoring default scan times.

That said we have pending changes (we are testing them as we speak) for more reliable on time scanning even if phone goes into deep sleep.

I think I misread your original question. You tuned scan time to 30 minutes?
FYI: we have a notion of scan time (active scanning) and wait time (not scanning, letting battery rest).

It just have struck me. Where do you hold reference to BeaconManager? If in Activity then after one hour your activity can be stopped and destroyed. For longer periods of ranging, it is better to store BeaconManager inside you Application class.

I want to explain in detail. I am doing this operation in my custom service.
I made my service a foreground service. App is working as expected when the phone is awake.

My main problem is BeaconManager.RanginListener is not working properly when the phone is sleeping. According to my code, waiting time should be 3 seconds between two scan. As far as the phone is in the sleep mode, waiting time increasing like 3, 4, 12, 21, 30 minutes. I think phone enter deep sleep mode and waiting time is not what I want it to be.

I want to set and observe a fixed waiting time even if the phone is in the deep sleep mode.
Here is my shortened code.

public class BluetoothService extends Service {

    private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("rid", null, null, null);
    public static BeaconManager beaconManager;
    private static String lastSeenBeaconMAC = "";
    MyBeaconRangingListener rangingListener;
    private String proximityString = "";

    @Override
    public void onCreate() {
        super.onCreate();
        if (beaconManager == null) {
            beaconManager = new BeaconManager(this);
        }
        if (rangingListener == null) {
            rangingListener = new MyBeaconRangingListener();
        }
        beaconManager.setRangingListener(rangingListener);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        connectToService();
        turnOnForegroundService("Content");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            beaconManager.stopRanging(ALL_ESTIMOTE_BEACONS_REGION);
            beaconManager.disconnect();
        } catch (RemoteException e) {
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void connectToService() {
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                try {
                    beaconManager.setBackgroundScanPeriod(2000, 3000);
                    beaconManager.setForegroundScanPeriod(2000, 3000);
                    beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
                } catch (RemoteException e) {
                }
            }
        });
    }

    public class MyBeaconRangingListener implements BeaconManager.RangingListener {

        @Override
        public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
            try {
                Double accuracy = Utils.computeAccuracy(beacons.get(0));
                Proximity nearestBeaconProximity = Utils.proximityFromAccuracy(accuracy);
                proximityString = "";
                switch (nearestBeaconProximity) {
                    case IMMEDIATE: proximityString = "IMMEDIATE";
                        break;
                    case NEAR: proximityString = "NEAR";
                        break;
                    case FAR: proximityString = "FAR";
                        break;
                    default: proximityString = "UNKNOWN PROXIMITY";
                        break;
                }
                //Calling Rest Service according to my business.

            } catch (Exception e) {
            }
        }
    }
}

Can you switched to the newest SDK? I noticed that you are using one from older releases.

Is your Service in remote process? Why do you need it at all?

I switched to the newest SDK and tested it again.
Result is much better but problem still goes on.
Waiting time should be 3 seconds between two scan but it reaches 14 minutes. (old SDK reached 30 minutes)

I created tracking bug for that on GitHub: https://github.com/Estimote/Android-SDK/issues/130
Please do star it to get notification on development.