Closed salex996 closed 7 months ago
I read your issue, but I do not know a reason your iBeacons are not showing.
Did the iBeacon show up in the example app's scan? Is iBeacon an Apple Tag? I see a whole bunch of various Apple devices showing up from the neighbors surrounding me, but I cannot tell which one is an Apple Tag and which one is not. Also note that I own Tile and Nut (that uses Nordic Semi) beacons and FBP sees all of them.
First of all, you need to enable location to be able to scan BT beacons, also pass androidUsesFineLocation: true
to the startScan
method. Make sure you add all required code to the AndroidManifest
file (see official docs of FBP).
Here's code that works for me:
// Start scanning
await FlutterBluePlus.startScan(timeout: const Duration(seconds: 4), androidUsesFineLocation: true);
_scanSubscription = FlutterBluePlus.scanResults.listen((scanResult) {
for (var result in scanResult) {
Map<String, dynamic> iBeaconData = convertAdvertisementDataToIBeaconData(result);
if (iBeaconData.isNotEmpty) {
// Do something with your converted data
}
}
}
});
// Cancel this subscription when scan is finished
FlutterBluePlus.cancelWhenScanComplete(_scanSubscription!);
And here is the convertAdvertisementDataToIBeaconData
function - I use it to recognize Estimote iBeacon devices:
Map<String, dynamic> convertAdvertisementDataToIBeaconData(ScanResult scanResult) {
Map<String, dynamic> iBeaconData = {};
if (scanResult.advertisementData.manufacturerData.containsKey(76) &&
scanResult.advertisementData.manufacturerData[76]!.length == 23 &&
scanResult.advertisementData.manufacturerData[76]![0] == 2 &&
scanResult.advertisementData.manufacturerData[76]![1] == 21) {
// print(">>>>> iBeacon found: ${scanResult.advertisementData.manufacturerData[76]}");
List<int>? data = scanResult.advertisementData.manufacturerData[76];
iBeaconData['remoteId'] = scanResult.device.remoteId.str;
iBeaconData['type'] = data![0];
iBeaconData['length'] = data[1];
iBeaconData['uuid'] = IBeaconModel.convertToUUID(data.sublist(2, 18));
iBeaconData['major'] = IBeaconModel.convertToInt(data.sublist(18, 20));
iBeaconData['minor'] = IBeaconModel.convertToInt(data.sublist(20, 22));
iBeaconData['pwr'] = data[22];
iBeaconData['rssi'] = scanResult.rssi;
}
return iBeaconData;
}
@spehj thanks.
I've added your info to the README.
Dear all,
It finally worked with the code @spehj sent,
However, I must say I needed to include few things in the androidManifest that I found in the library flutter_reactive_ble https://github.com/PhilipsHue/flutter_reactive_ble/tree/8d66469df06e814a96eed48174d34525459c62c5
They say something like:
'You need to add the following permissions to your AndroidManifest.xml file:
If you use BLUETOOTH_SCAN to determine location, modify your AndroidManfiest.xml file to include the following entry:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" tools:remove="android:usesPermissionFlags" tools:targetApi="s" />
If you use location services in your app, remove android:maxSdkVersion="30" from the location permission tags'
And after following this instructions I can see my beacons, :)
Just few more questions to @spehj
how is the class IBeaconModel? How can I access to data in IBeaconModel? And finally, It may be so obvious but how did you declare _scanSubscription? I am facing problems here,
Thank you very much for your support,
@salex996 can you look at the FBP documentation here? https://github.com/boskokg/flutter_blue_plus?tab=readme-ov-file#add-permissions-for-android-with-fine-location
Is it correct?
@chipweinberger FBP documentation is correct and works out of the box.
This part from the docs needs to be pasted to the android/app/src/mainÀndroidManifest.xml
:
<!-- Tell Google Play Store that your app uses Bluetooth LE
Set android:required="true" if bluetooth is necessary -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
<!-- New Bluetooth permissions in Android 12
https://developer.android.com/about/versions/12/features/bluetooth-permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- legacy for Android 11 or lower -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!-- legacy for Android 9 or lower -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
@salex996 IBeaconModel is just a simple model to store iBeacon data in organized way. It also has some static methods to calculate beacon distance from power (just approximate number in meters), convert bytes to int and UUID values.
_scanSubscription
is defined as StreamSubscription<List<ScanResult>?>? _scanSubscription;
. You can just assign it to a variable and let the FBP package cancel the subscription once the scan is finished. See my example project below.
I created this simple and unorganized project just to display how iBeacon scanner app can be made with Flutter Blue Plus. Note that this won't work for iOS.
Project: Minimal beacon scanner
Requirements
Have you checked this problem on the example app?
Yes
FlutterBluePlus Version
flutter_blue_plus: ^1.31.8
Flutter Version
3.16.7
What OS?
Android
OS Version
14
Bluetooth Module
Google Tensor G2
What is your problem?
Finally, I did a code that scans, however I can't find the two beacons that I am trying to find, I can find them using bluetoothctl in my fedora and using an app called nRF Connect from Nordic semiconductor in my phone, I also have checked all the points in the readme document but nothing works, actually I changed the adv protocol in the beacons so I have one of them sending messages in Eddystone UUID and the other one in iBeacon, but still I can't find them,
The ID of the beacons are E8:EB:1A:CB:56:CA and E5:9F:52:36:E9:BE and their names are GT_V101788 and GT_V101787 both from brand Global Tag S.L.,
Please, can you support me?
The code I did (the devices are really near so I tried to filter by rssi according to the values I obtained from the app nRF Connect):
List of the IDs detected in the set devicesId when I finished the code that I did: {68:6E:DA:C1:AB:AC, 50:99:9D:B7:89:F9, F8:4E:58:CF:94:A5, 69:6A:EB:4A:0B:F5, 76:22:67:38:67:A9, 65:F8:37:CC:76:EB, 44:07:F8:E0:2A:14, FD:35:27:5A:BC:83, D1:FF:9B:B3:BE:EC}
Find attached images from app nRF Connect:
Logs