Darshit Hedpara
Darshit Hedpara

Reputation: 670

Flutter : IOS to IOS Broadcast Beacon not working

I'm currently building an app that turns my device into a Beacon while simultaneously scanning for other Beacons. So I can keep track of beacons that I had come in contact with.


Problem

Current I've tested this code in the following Scenarios:

  1. Android TO Android - Broadcasting & Scanning - Working well
  2. Android To IOS - BroadCasting & Scanning Both ways - Working well
  3. IOS to IOS - Not Working (When I broadcast UUID from IOS Device, I can see UUID in Android device but I can't see UUID in any IOS device.)

This is very strange, and I need help to solve this, please!


I've currently implemented 2 packages to achieve this functionality :

(1) For broadcast

beacon_broadcast: https://pub.dev/packages/beacon_broadcast version : 0.2.1

(2) For scan other beacons

flutter_blue: https://pub.dev/packages/flutter_blue version : 0.6.3+1


These are some glimpse of my code

(1) For Broadcasting

String UUID = 'DYNAMIC_UUID_FOR_EACH_DEVICE';
static const MAJOR_ID = 1;
static const MINOR_ID = 30;
static const TRANSMISSION_POWER = -59;
static const IDENTIFIER = 'com.example.myDeviceRegion';
static const LAYOUT = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24';
static const MANUFACTURER_ID = 0x004c;

BeaconBroadcast beaconBroadcast = BeaconBroadcast();
beaconBroadcast
   .setUUID(UUID)
   .setMajorId(MAJOR_ID)
   .setMinorId(MINOR_ID)
   .setTransmissionPower(TRANSMISSION_POWER)
   .setIdentifier(IDENTIFIER)
   .setLayout(LAYOUT)
   .setManufacturerId(MANUFACTURER_ID);
   .start();

(2) For Scanning

FlutterBlue flutterBlue = FlutterBlue.instance;
flutterBlue.startScan(timeout: Duration(seconds: 30));
flutterBlue.scanResults.listen((List<ScanResult> results) {
  print('scanningListen...');
  for (ScanResult result in results) {
      result.advertisementData.manufacturerData.forEach((item, hexcodeAsArray) => {
         print("calculated UUID String : " + calculateHexFromArray(v));
         _addToScanResult(calculateHexFromArray(v));
      });
  }
}
String calculateHexFromArray(decimalArray) {
  String uuid = '';
  decimalArray.forEach((i) => {uuid += i.toRadixString(16).padLeft(2, '0')});
  String uuid1 = uuid.substring(4, uuid.length - 12);
  return uuid1.toUpperCase();
}

Upvotes: 3

Views: 1645

Answers (1)

davidgyoung
davidgyoung

Reputation: 64961

Unfortunately, you cannot use FlutterBlue to detect iBeacon packets on iOS.

Why? FlutterBlue uses raw bluetooth scanning to detect beacons, which under the hood means using the native CoreBluetooth scanning APIs on iOS. Apple blocks CoreBluetooth APIs from reading the raw bytes of any bluetooth advertisement decodable as an iBeacon advertisement. While this may sound crazy, it is likely motivated by misguided security concerns by Apple. Read more in my blog post here: CoreBluetooth Doesn't Let You See iBeacons

Two options to fix this:

  1. Switch to using the AltBeacon format. Simply change LAYOUT = 'm:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25'; and MANUFACTURER_ID = 0x0118;

    This will work, but has the disadvantage of the advertisement only being detectable on iOS in the foreground.

  2. Switch to using a different detection library on iOS that uses CoreLocation (the only API allowed to detect iBeacon on iOS) instead of CoreBluetooth. That means giving up FlutterBlue in favor of FlutterBeacon or similar.

Upvotes: 2

Related Questions