Estimote / Android-Fleet-Management-SDK

Estimote Fleet Management SDK for Android
https://developer.estimote.com
MIT License
836 stars 451 forks source link

Estimode SDK 1.0.12 to 1.1.0 can't recall onExitedRegion() on Andorid 7.1.1 #250

Closed LawsD closed 6 years ago

LawsD commented 7 years ago

My test device is Nokia 6 with Android 7.1.1 and the beacons are Location Beacons. The configurations are

I separately tested the Example/Notification demo with SDK from 1.0.8(default in the demo) to 1.1.0 and found that from 1.0.12 the Monitoring can't recall onExitedRegion() so I can't receive the exiting event when I flip my beacons. At first, I followed the tutorial on the Developer Docs and set the SDK to 1.0.12 and found I can't receive the exiting event until I set it back to 1.0.8. By the way, on each SDK version, I waited for at least 2 mins to get the exiting event.

In addition, the "setRegionExitExpiration(1000);" seems to never be affective.

bjellicious commented 6 years ago

TL;DR

Something is bugged with onExitedRegion, and it is still present in 1.3.0. It seems to work fine in 1.0.8, but if you want it to work in later versions it seems you can do ranging at the same time to make it work (if other beacons are in range). It seems to not call onExitedRegion until another beacon/region is found.

Below is what I have discovered so far.


I can also confirm this problem, and I know others who have ran into it as well. I have done about 8-9 hours of different setups, and there are for sure something weird with onExitedRegion(). I also waited for at least 2 minutes after onEnteredRegion() was called (I flipped the beacons to sleep right after, although I have tested with waiting before flipping to sleep as well). I have tested with my own project, the Estimote Airport example and monitoring example. I have tested with a Samsung Galaxy S8+ and a Samsung Galaxy S6. After a handful of hours with frustration, I started testing and doing things as simple as possible, so I started to try and only deal with one beacon (Enter and Exit one beacons region). The entering part is always working, the exiting part is rarely (when it sees other beacons).

The code below started out as the Estimote Airport example, which I downloaded and imported into Android Studio. During the testing it was modified and simplified, but the base is that project.

Code which works fine with SDK 1.0.8

public class MyApplication extends Application {
    private String TAG = "EstimoteAirport";
    private BeaconManager beaconManager;

    //Todo Change to appropriate settings
    private UUID uuid = UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D");
    private int majorOfBeacon = 201;
    private int minorOfBeacon = 302;

    public BeaconRegion beaconRegion1 = new BeaconRegion("Region1", uuid, majorOfBeacon, minorOfBeacon);
    //public BeaconRegion beaconRegion2 = new BeaconRegion("Region2", uuid, majorOfBeacon, null);
    //public BeaconRegion beaconRegion3 = new BeaconRegion("Region3", uuid, null, null);

    @Override
    public void onCreate() {
        super.onCreate();
        EstimoteSDK.initialize(getApplicationContext(), "<Here goes your application ID>", "<Here goes your application token>");
        beaconManager = new BeaconManager(getApplicationContext());
        setupMonitoringListener();
        startMonitoring();
    }

    public void startMonitoring(){
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                beaconManager.startMonitoring(beaconRegion1); //beaconRegion1, beaconRegion2, beaconRegion3
            }
        });
    }

    public void setupMonitoringListener(){
        beaconManager.setMonitoringListener(new BeaconManager.BeaconMonitoringListener() {

            @Override
            public void onEnteredRegion(BeaconRegion beaconRegion, List<Beacon> beacons) {
                Log.v(TAG, "Entered range of " + beaconRegion.getMajor() + ":" + beaconRegion.getMinor());
                Log.v(TAG, "Beacons in range:" + beacons.toString());
            }

            @Override
            public void onExitedRegion(BeaconRegion beaconRegion) {
                Log.v(TAG, "Exited range of " + beaconRegion.getMajor() + ":" + beaconRegion.getMinor());
            }
        });
    }
}

On 1.0.8 the result are:

10-03 10:19:20.680 20257-20257/com.example.airport V/EstimoteAirport: Entered range of 201:302
10-03 10:19:20.683 20257-20257/com.example.airport V/EstimoteAirport: Beacons in range:[Beacon{macAddress=[CD:BF:35:C3:0B:29], proximityUUID=b9407f30-f5f8-466e-aff9-25556b57fe6d, major=201, minor=302, measuredPower=-76, rssi=-73}]
10-03 10:20:30.699 20257-20257/com.example.airport V/EstimoteAirport: Exited range of 201:302

On 1.3.0 the result are:

10-03 10:25:00.064 26004-26004/com.example.airport V/EstimoteAirport: Entered range of 201:302
10-03 10:25:00.067 26004-26004/com.example.airport V/EstimoteAirport: Beacons in range:[Beacon{macAddress=[CD:BF:35:C3:0B:29], proximityUUID=b9407f30-f5f8-466e-aff9-25556b57fe6d, major=201, minor=302, measuredPower=-76, rssi=-70, timestamp=2017-10-03}]

(no exit, doesn't matter if I wait 5 or 15 minutes)


Can work with SDK's after 1.0.8

But I am able to make it work on 1.3.0, if I do ranging at the same time and other beacons are to be found. It seems that on after 1.0.8, it only notices that it exits a region (or loses contact with a beacon) if it sees other beacons/regions. So if we run the code below as well, it produces the results which can be seen at the bottom (more details about each result is written after each result). Here's the code for the Activity where the ranging happens:

public class MainActivity extends AppCompatActivity {
    private BeaconManager beaconManager;
    private BeaconRegion region;
    private String TAG = "EstimoteAirport";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SystemRequirementsChecker.checkWithDefaultDialogs(this);
        setupRanging();
    }

    @Override
    protected void onResume() {
        super.onResume();
        SystemRequirementsChecker.checkWithDefaultDialogs(this);
        startRanging();
    }

    public void setupRanging(){
        beaconManager = new BeaconManager(this);
        beaconManager.setRangingListener(new BeaconManager.BeaconRangingListener() {

            @Override
            public void onBeaconsDiscovered(BeaconRegion beaconRegion, List<Beacon> beacons) {
                if (!beacons.isEmpty()) {
                    for (Beacon beacon : beacons){
                        Log.v(TAG, beacon.getMajor() + ":" + beacon.getMinor());
                    }
                    Log.v(TAG, "-----------");
                }
            }
        });
        region = new BeaconRegion("ranged region", UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
    }

    protected void startRanging(){
        beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
            @Override
            public void onServiceReady() {
                beaconManager.startRanging(region);
            }
        });
    }

}

Results that show it works in 1.3.0, with ranging and other beacons present

On 1.3.0 I manage to get these kinds of results consistently : (Don't worry about missing timestamps, I removed alot of duplications)

The UUID of all the beacons is set to standard (also those who are not mine). I try to trigger events for the beacon with a major of: 201 and minor of 302 (201:302). I also have a beacon with a major of 201 and minor of 301 (201:301). The other beacons are just present all the time, as they are not mine.

Note that the Application class is never changed through this testing. It is only the ranging regions (in the MainActivity (setupRanging()) I am changing here.


First result (ranging region: UUID, null, null):

10-03 10:27:34.602 30676-30676/com.example.airport V/EstimoteAirport: 10185:22840
10-03 10:27:34.602 30676-30676/com.example.airport V/EstimoteAirport: 59345:17776
10-03 10:27:34.603 30676-30676/com.example.airport V/EstimoteAirport: 10185:13436
10-03 10:27:34.603 30676-30676/com.example.airport V/EstimoteAirport: -----------
10-03 10:27:35.612 30676-30676/com.example.airport V/EstimoteAirport: Entered range of 201:302
10-03 10:27:35.615 30676-30676/com.example.airport V/EstimoteAirport: Beacons in range:[Beacon{macAddress=[CD:BF:35:C3:0B:29], proximityUUID=b9407f30-f5f8-466e-aff9-25556b57fe6d, major=201, minor=302, measuredPower=-76, rssi=-89, timestamp=2017-10-03}]
10-03 10:27:35.615 30676-30676/com.example.airport V/EstimoteAirport: 10185:22840
10-03 10:27:35.615 30676-30676/com.example.airport V/EstimoteAirport: 59345:17776
10-03 10:27:35.615 30676-30676/com.example.airport V/EstimoteAirport: 201:302
10-03 10:27:35.615 30676-30676/com.example.airport V/EstimoteAirport: 10185:13436

10-03 10:28:00.211 30676-30676/com.example.airport V/EstimoteAirport: 10185:13436
10-03 10:28:00.211 30676-30676/com.example.airport V/EstimoteAirport: 10185:22840
10-03 10:28:00.211 30676-30676/com.example.airport V/EstimoteAirport: 59345:17776
10-03 10:28:00.211 30676-30676/com.example.airport V/EstimoteAirport: -----------
10-03 10:28:00.212 30676-30676/com.example.airport V/EstimoteAirport: Exited range of 201:302
10-03 10:28:01.236 30676-30676/com.example.airport V/EstimoteAirport: 10185:13436
10-03 10:28:01.237 30676-30676/com.example.airport V/EstimoteAirport: 59345:17776
10-03 10:28:01.237 30676-30676/com.example.airport V/EstimoteAirport: 10185:22840
10-03 10:28:01.237 30676-30676/com.example.airport V/EstimoteAirport: -----------
10-03 10:28:02.255 30676-30676/com.example.airport V/EstimoteAirport: 10185:13436
10-03 10:28:02.255 30676-30676/com.example.airport V/EstimoteAirport: 59345:17776
10-03 10:28:02.255 30676-30676/com.example.airport V/EstimoteAirport: 10185:22840
10-03 10:28:02.255 30676-30676/com.example.airport V/EstimoteAirport: -----------

Note that the in this result, we are looking for beacons in the region (standard UUID, null, null), and that works because it sees the beacons in the office on the other side of the wall as well. With this setup, the onEntered and onExited works as one would expect.


Second result (ranging region: UUID, 201, null):

10-03 10:37:42.731 4344-4344/com.example.airport V/EstimoteAirport: Entered range of 201:302
10-03 10:37:42.735 4344-4344/com.example.airport V/EstimoteAirport: Beacons in range:[Beacon{macAddress=[CD:BF:35:C3:0B:29], proximityUUID=b9407f30-f5f8-466e-aff9-25556b57fe6d, major=201, minor=302, measuredPower=-76, rssi=-72, timestamp=2017-10-03}]
10-03 10:37:42.756 4344-4344/com.example.airport V/EstimoteAirport: 201:302
10-03 10:37:42.756 4344-4344/com.example.airport V/EstimoteAirport: -----------

10-03 10:38:48.973 4344-4344/com.example.airport V/EstimoteAirport: 201:301
10-03 10:38:48.973 4344-4344/com.example.airport V/EstimoteAirport: -----------
10-03 10:38:48.974 4344-4344/com.example.airport V/EstimoteAirport: Exited range of 201:302

10-03 10:39:04.296 4344-4344/com.example.airport V/EstimoteAirport: 201:301
10-03 10:39:04.296 4344-4344/com.example.airport V/EstimoteAirport: -----------

In the second result, I use region (standard UUID, 201, null), as I have the two beacons with the major of 201 (So I then filter out the other office's beacons).

What is happening here is that I start with both beacons turned off. Then I turn on the beacon I actually want (201:302) (then comes the onEnterRegion()). Then I flip it to turn it off (and there is no onExitRegion()). Then I turn on the second beacon (201:301), and then the onExitedRegion() for (201:302) comes.


Third result (ranging region: UUID; 201, null):

10-03 11:05:55.038 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:05:56.051 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:05:56.052 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:05:57.066 3425-3425/com.example.airport V/EstimoteAirport: Entered range of 201:302
10-03 11:05:57.070 3425-3425/com.example.airport V/EstimoteAirport: Beacons in range:[Beacon{macAddress=[CD:BF:35:C3:0B:29], proximityUUID=b9407f30-f5f8-466e-aff9-25556b57fe6d, major=201, minor=302, measuredPower=-76, rssi=-80, timestamp=2017-10-03}]
10-03 11:05:57.070 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:05:57.070 3425-3425/com.example.airport V/EstimoteAirport: 201:302
1
10-03 11:06:19.137 3425-3425/com.example.airport V/EstimoteAirport: 201:302
10-03 11:06:19.137 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:19.137 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:06:20.148 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:20.149 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:06:22.191 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:22.191 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:06:22.192 3425-3425/com.example.airport V/EstimoteAirport: Exited range of 201:302
10-03 11:06:23.218 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:23.218 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:06:24.238 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:24.238 3425-3425/com.example.airport V/EstimoteAirport: -----------
10-03 11:06:25.259 3425-3425/com.example.airport V/EstimoteAirport: 201:301
10-03 11:06:25.259 3425-3425/com.example.airport V/EstimoteAirport: -----------

Now this third result is similair to the first and second one, except the second beacon (201:301) is on the whole time. Which then makes the onEnteredRegion() and onExitedRegion() for the beacon we want (201:302) behave as it should.

pawelDylag commented 6 years ago

Hey! I just wanted you to know that we are in the process of moving our SDK for Android to a completely new architecture. We won't be publishing any updates to our old (current master) SDK for a while.

But don't worry - there is an ALPHA version of our FRESH PROXIMITY SDK available now! It uses a completely new scanning mechanism and will work on new Android versions like a charm (6.0, 7.0, 8.0). We did a great job with renovating our ecosystem to cut off the old, messy code, full of hacks for Android KitKat an Jellybean. This is why working with BeaconManager was so frustrating by the way.

Plan for the next couple of weeks:

  1. ProximitySDK beta release - our own tag-based proximity. Use it to achieve the same behaviour as using iBeacon (monitoring/ranging). It is uses our own packets called Estimote Location and is backed-up by our own data-science. Read more here -> http://blog.estimote.com/post/166007374930/the-most-reliable-proximity-tech-now-with-a
  2. ScanningSDK beta release - a separate core library dedicated for raw scanning - it will handle the scanning on all android versions for you, battery efficiency, background/foreground, and will deliver raw stream of packet data (Such as iBeacon, Eddystone, EstimoteLocation, EstimoteTelemetry, etc).

I encourage you to try it out - there is a ready made app for you to show the possibilities of our completely new SDK -> https://github.com/Estimote/Android-SDK/tree/proximity-sdk Let us know what you think! I will keep you updated about the progress.