AltBeacon / android-beacon-library

Allows Android apps to interact with BLE beacons
Apache License 2.0
2.83k stars 836 forks source link

2.9.1 no longer finds beacons after killing the app #451

Closed AlexLardschneider closed 7 years ago

AlexLardschneider commented 7 years ago

Hello, after updating from 2.7.1 to 2.9.1 I noticed the library no longer finds beacons after I kill the app and it restarts itself. On 2.7.1 I started the beacon manager inside a Service with the START_STICKY flag, which would automatically restart itself after the app has been killed. didEnterRegion and didRangeBeaconsInRegion were called accordingly (e.g. the library finds one beacon, it gets killed, restarts itself and can still find that one beacon).

On 2.9.1 however I noticed the library automatically restarts itself after it has been killed, but does no longer find the beacon which was previously visible (didRangeBeaconsInRegion is no longer called). I noticed however that after enabling logging by using BeaconManager.setDebug(true) the log gets spammed with a lot of beacon information, which indicates that the device can still see the beacon.

I attached a sample app to reproduce the error. Run the app and start a beacon, the app should see it. Then kill it by using the little red cross in the LogCat window. The app should restart but no longer find any beacons (didEnterRegion and didRangeBeaconsInRegion are not called, not even after a couple of minutes or a restart of the beacon. Rebuilding the app from within Android Studio however fixes the issue).

Expected behavior

After killing the app, the library should restart itself and find beacons.

Actual behavior

It starts itself, but cannot find any beacons.

Steps to reproduce this behavior

I attached a sample app which should reproduce the issue. If not, I provided the output of my LogCat so you can see what is happening on my device.

Mobile device model and OS version

Samsung Galaxy S5 (klte) running CM14.1 (Android 7.1)

Android Beacon Library version

2.9.1, used 2.7.1 before which worked fine.

Attached files:

AltBeaconSample.zip LogCat.txt

davidgyoung commented 7 years ago

@Alexlardschneider, can you please clarify what you mean by "Rebuilding the app from within Android Studio however fixes the issue"?

AlexLardschneider commented 7 years ago

@davidgyoung I mean running the app from Android Studio, which then updates/reinstalls the app and restarts it fixes the issue. A normal restart of the app from the app drawer however does not fix the problem. Sorry for the confusion.

davidgyoung commented 7 years ago

Reviewing the log, I see the beacon service starts twice. Presumably the second startup is after killing the app sometime before 20:12, yes?

11-13 20:11:53.454 29350-29350/com.example I/BeaconService: beaconService version 2.9.1 is starting up

11-13 20:12:02.899 29580-29580/com.example I/BeaconService: beaconService version 2.9.1 is starting up

In both cases, I see that beacons are detected and even in the second case, it looks like the enter region is called here:

11-13 20:12:00.196 29350-29545/com.example I/BeaconHandler: didDetermineStateForRegion(): state=1
11-13 20:12:00.196 29350-29545/com.example E/BeaconHandler: didEnterRegion() BUS

Bottom line: I don't see any problem in the logs. Are you certain the code is not getting callbacks? Because the log entry at 20:12:00.196 suggests it is.

One other point: I see that the sample code creates two instances of RegionBootstrap. This is not the intended use of the class, and I am unsure it will work correctly. If you want to set up two different regions, then there is an alternate constructor for RegionBootstrap that takes a collection of regions. I'm not sure if this is contributing to this issue but it is certainly possible.

AlexLardschneider commented 7 years ago

The System.exit called, status: 1 call at 20:12:01.633 marks the point where the app was killed from Android Studio. After that point I can see calls to didDetermineStateForRegion (), but no further calls to didEnterRegion() or didRangeBeaconsInRegion(). Only didExitRegion() gets called somewhere at the end of the log.

I tried using the constructor new RegionBootstrap(this, Arrays.asList(mRegionBus, mRegionBusStop));to create the bootstrap, but that did not fix the problem.

davidgyoung commented 7 years ago

OK, I think we've found the problem!

As of version 2.9, the library will remember the state of each Region being monitored across app restarts. If you have a brief restart (due to memory pressure, force killing the app, etc) the app will remember that it was already in region and it won't send a subsequent didEnterRegion callback. This is intended behavior with the idea being to prevent multiple spurious entry events.

So it isn't true that the library won't find beacons as this title describes, but it is true that it won't re-send entry events when it knows you were already in region a few seconds ago when the app was previously running.

If you don't want this behavior, you can call BeaconManager.setRegionStatePeristenceEnabled(false)

AlexLardschneider commented 7 years ago

@davidgyoung Adding BeaconManager.setRegionStatePeristenceEnabled(false) did solve my problem, thanks!

AlexLardschneider commented 7 years ago

Also I noticed that starting the beacon scanning from inside a RxJava subscription which is observed on the main thread (via AndroidSchedulers.mainThread()) will not deliver results after it is killed.

You can test this for yourself using this sample code:

Observable.just(1)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer i) {
                        BeaconHandler beaconHandler = BeaconHandler.get(getApplicationContext());
                        beaconHandler.startListening();
                    }
                });

The first time you run the app it delivers results to didRangeBeaconsInRegion (), but after you kill it and it restarts itself no more callbacks to didRangeBeaconsInRegion () are delivered. Removing observeOn(AndroidSchedulers.mainThread()) solves that problem.

This happens no matter if region state persistence is enabled or disabled.

Should I open a separate issue about this?