5
votes

I'm fairly new to iBeacon but I have spent the day trying to get informations and a working Android application with iBeacon.

I have stumbled upon Android iBeacon Library samples and gave it a try. I used the latest aar file (0.7.3) and basically copy/paste their examples in a new project. I have created a beacon using an iPad with AirLocate (compiled from Apple's code from the Dev Center) and launch the code.

My problem is the range fluctuating all the time with no logic. For example, the phone (in this case a Nexus 5, original rom, no modification) placed half a meter away from the iPad gives me the following measures :

  • 0.01m
  • 0.03m
  • 0.07m
  • 0.48m
  • 0.01m
  • 0.02m

etc.

When I use another iPad with AirLocate on it, it gives a more stable and realistic measure. Excluding the beacon as the source of the problem.

I have made the test with a Nexus 7 2013 (Original rom, not modified) and I got the same issue. I have read the wifi can cause problem so I disabled it but it is still the same. I also have the same issue with Radius Networks application on the Play Store: iBeacon Locate

I was wondering if the anyone else have the problem with this library ? Is there something I can do to help fix this problem ? Do you know another library I can use which won't cause that kind of problem ?

Any help is appreciate. Thank you in advance.

1

1 Answers

13
votes

A big part of the variation you see is Android is caused by a limitation in the way Android allows access signal strength measurements from Bluetooth LE. Unfortunately, there isn't much that can be done about this without changes to Android.

In both iOS CoreLocation and the Android iBeacon Library, the distance estimate is only an estimate, and fluctuations with noise on signal strength measurements cause the estimates to bounce around.

The algorithm in the Android iBeacon Library is not the same as in iOS CoreLocation, because the iOS CoreLocation implementation is closed source. The intention is that they behave in a similar way. The Android iBeacon Library is based on a 10 second running average of 80th percentile measurements (e.g. the top and bottom 10th percentile measurements are thrown away for the average.) You can see the details of the calculation here:

protected static double calculateAccuracy(int txPower, double rssi) {
  if (rssi == 0) {
    return -1.0; // if we cannot determine accuracy, return -1.
  }

  double ratio = rssi*1.0/txPower;
  if (ratio < 1.0) {
    return Math.pow(ratio,10);
  }
  else {
    double accuracy =  (0.89976)*Math.pow(ratio,7.7095) + 0.111;    
    return accuracy;
  }
}   

On Android, the Bluetooth LE Scan API only allows a single signal strength measurement per scan. On iOS, it is possible to get a different measurement for each advertisement broadcasted. By default, the Android iBeacon Library does one bluetooth scan every 1.1 seconds when it is in the foreground, therefore allowing one measurement every 1.1 seconds. So if you have an iBeacon that is transmitting 30 times per second (as iOS devices acting as iBeacons do), iOS will be able to get 300 samples in a 10 second period, and Android only 9. This explains why the estimate has higher noise on Android. And again, there is very little that can be done about it without operating system changes.

Depending on your use case, you may be able to reduce the noise in the distance estimate on Android by implementing a custom calculation that includes more samples over a longer period of time. This would only be appropriate if your use case does not need rapid updates in the estimate. If you are interested in this, you might open a feature request in the open source library.