Some facts

  • Android is notoriously bad with its Bluetooth stack.
  • New BT API introduced in Lollipop makes it somewhat better (however brings new set of problems).
  • Proxi.cloud SDK v1.x uses old BT API only.
  • The SDK v2 using new BT API is on its way!

Standard practice

In some approaches, exit time was defined as absolute time since the last seen beacon, minus only last scan pause time. The exit condition was checked every second of the scan time. This solution is not inherently bad, but combined with using old API and somewhat crooked implementation, it had problems:

  • Exit could be triggered after 1 second of scan, followed immediately by enter.
  • Subtracting only last pause time limited it to 2 scan cycles max.
  • In case of Android BT error (infamous status=133) false exits were triggered.
  • In general, exits were quickly triggered, but very inconsistently.

The proxi.cloud solution

In the proxi.cloud SDK exit time is defined as a sum of scan times we haven’t seen given beacon. There is also grace period from the beginning of every scan when exit can’t be triggered, even though the exit time has passed. This solution results in:

  • More control over exit behavior.
  • Elasticity to mimic the old exit strategy through using Settings (link here).
  • Grace time protecting from exiting right at beginning of the scan.
  • Less false exits in case of Android BT error occuring.
  • In general, exits are slower but way more consistent and configurable, so better suited for real world cases.

Let's consider behavior of SDK 1.x.x on its default settings, while app is in background:

{
    "scanner.exitTimeoutMillis": 40000,
    "scanner.backgroundScanTime": 15000,
    "scanner.backgroundWaitTime": 120000,
    "scanner.exitBackgroundGraceMillis": 7500
}

Translated to graph this is:

Legend

Let's assume the beacon was last seen 3s after the first scan cycle started:

Example

Time needed for exit is 40s, so we need to finish the first cycle (12s), run second cycle (15s) and then exit is triggered in third cycle (after 13s of it). If the exit should appear in first 7.5s of the scan (grace time) it will be delayed till the end of the grace time.

In case of Android optimizing AlarmManager alerts the 120s wait time above may easily become 300s, thus prolonging exit times even further (up to 15 mins). The default settings are very defensive, resulting in stable exits even for worse phones, but may not be what you want. If your case needs quicker exits (but less consistency on older phones) experiment with lower exit timeout, e.g:

{
    "scanner.exitTimeoutMillis": 20000
}

The Future

Proper solution is using new BT API combined with burst scanning (splitting scan time into sub-scans), plus grace time and possibly some hard-limited time of exit defined as absolute time since we’ve seen beacon.

And it’s coming soon!