AltBeacon / android-beacon-library

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

didRangeBeaconsInRegion called once per 1.1 second #1079

Closed ipython3 closed 2 years ago

ipython3 commented 2 years ago

Expected behavior

In API JavaDoc, description of didRangeBeaconsInRegion is "Called once per second", description of its parameter beacons is "a collection of Beacon objects that have been seen in the past second".

Actual behavior

But from timestamp of my log, I found that this method is called once per 1.1 second.

2022-03-27 17:01:36.707
2022-03-27 17:01:37.815
2022-03-27 17:01:38.924
2022-03-27 17:01:40.029
2022-03-27 17:01:41.138
2022-03-27 17:01:42.244
2022-03-27 17:01:43.349
2022-03-27 17:01:44.456

Steps to reproduce this behavior

        BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
        beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(IBEACON_FORMAT));
        beaconManager.addRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                for (Beacon beacon : beacons) {
                    Log.d(TAG, beacon.getId1().toString()+", "+beacon.getId2().toString()+", "+beacon.getId3().toString()+", "+beacon.getRssi());
                }
            }
        });

        beaconManager.startRangingBeacons(new Region("myRegion", null, null, null));

I noticed that beaconManager.getForegroundScanPeriod() returns 1100, and I guess this is the default value. Has the default value been set incorrectly? (since it makes didRangeBeaconsInRegion getting called per 1.1 second) Is there any reason to choose this value?

Android Beacon Library version

2.19.4

davidgyoung commented 2 years ago

Yes, this is expected behavior. The JavaDoc should probably be updated to say, "Called approximately once per second with default settings."

The reason it is set to 1100ms is largely for historical reasons. Early Android phones supporting Bluetooth LE like the Nexus 4 would refuse to return a second detection for the same device until a scan was stopped and a new one started. If the scan period were set to exactly 1000ms there was a possibility that timing of the scans would cause trouble with beacons advertising at only 1Hz. When you stop and restart scanning, there are a few ms where no scan is going on, and any packets being transmitted over the air at that time can not be received. Setting the default scan period to 1100ms instead of 1000ms made it much more unlikely that the scan boundaries would always fall across a 1Hz beacon transmission.

More modern Android phones no longer require stopping and restarting scans in order to detect a beacon again, and the library now halts this stop/start behavior as soon as it detects that a phone can detect more than one beacon packet in a single scan. The historic behavior is retained for backward compatibility, but is planned to be removed in the 3.0 release.

ipython3 commented 2 years ago

Thank you for answering in such detail! I really appreciate it.