bluetooth lowenergy - Can't Discover BLE LE-Only Devices (Beacons) on Android 12+ Using React Native BLE Libraries - Sta

I'm developing a React Native app that scans for Bluetooth Low Energy (BLE) devices, specifically

I'm developing a React Native app that scans for Bluetooth Low Energy (BLE) devices, specifically LE-only devices (Beacons). The app works perfectly on Android devices running Android 11 (SDK 30) or lower, discovering the Eartags without any issues. However, on devices running Android 12 (SDK 31) and above, the app fails to discover these LE-only devices, although it can still find other Bluetooth devices.

I've tried multiple BLE libraries, including react-native-ble-manager and react-native-ble-plx, but the problem persists. Interestingly, when using nRF Connect on the same Android 12+ devices, the Tags are discovered without any issues, displaying the correct MAC addresses and local names.

I've spent considerable time trying to resolve this issue, including adjusting permissions, scanning settings, and handling advertising data, but haven't found a solution. I'm hoping someone can help me identify what's going wrong.

What I've Tried:

Permissions:

  • Updated AndroidManifest.xml with all necessary permissions.
  • Requested runtime permissions, including BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and ACCESS_FINE_LOCATION.
  • Ensured location services are enabled on the device.

Scanning Code:

  • Removed all filters during scanning to allow all devices to be discovered.
  • Adjusted scanning settings, including allowDuplicates, scanMode, and matchMode.
  • Logged full device objects during scanning to analyze available data.

Libraries:

  • Tried both react-native-ble-manager and react-native-ble-plx to perform scanning.
  • Updated libraries to the latest versions to ensure compatibility with Android 12+.

Testing:

  • Created a minimal app focused solely on scanning for BLE devices.
  • Tested on multiple Android 12+ devices to rule out device-specific issues.
  • Compared app behavior with nRF Connect, which successfully discovers the Eartags.

Permissions in AndroidManifest.xml:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Android 12+ Permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Scanning & Permission Function


const bleManager = new BleManager();

const startScan = async () => {
  try {
    const permissionsGranted = await checkPermissions();
    if (!permissionsGranted) {
      console.log('Permissions not granted');
      return;
    }

    bleManager.startDeviceScan(
      null,
      { allowDuplicates: true },
      (error, device) => {
        if (error) {
          console.error('Scan error:', error);
          return;
        }

        // Log the full device object
        console.log('Discovered device:', JSON.stringify(device, null, 2));

        if (isEartag(device)) {
          console.log('Eartag found:', device.id);
        }
      },
    );

    // Stop scanning after a set duration
    setTimeout(() => {
      bleManager.stopDeviceScan();
      console.log('Scan stopped');
    }, 5000);
  } catch (error) {
    console.error('Scan error:', error);
  }
};

const checkPermissions = async () => {
    try {
      if (Platform.OS === 'ios') {
        return true;
      }
      if (
        Platform.OS === 'android' &&
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
      ) {
        const apiLevel = parseInt(Platform.Version.toString(), 10);

        if (apiLevel < 31) {
          const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          );
          return granted === PermissionsAndroid.RESULTS.GRANTED;
        }
        if (
          PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN &&
          PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
        ) {
          const result = await PermissionsAndroid.requestMultiple([
            PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
            PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
            PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          ]);

          return (
            result['android.permission.BLUETOOTH_CONNECT'] ===
              PermissionsAndroid.RESULTS.GRANTED &&
            result['android.permission.BLUETOOTH_SCAN'] ===
              PermissionsAndroid.RESULTS.GRANTED &&
            result['android.permission.ACCESS_FINE_LOCATION'] ===
              PermissionsAndroid.RESULTS.GRANTED
          );
        }
      }
      showErrorToast('Permission have not been granted');
      return false;
    } catch (error) {
      console.error('Error in permission check:', error);
      return false;
    }
  };

Devices that I try to find (nRF Connect on the same device)

nRF Connect Screenshot

I'm developing a React Native app that scans for Bluetooth Low Energy (BLE) devices, specifically LE-only devices (Beacons). The app works perfectly on Android devices running Android 11 (SDK 30) or lower, discovering the Eartags without any issues. However, on devices running Android 12 (SDK 31) and above, the app fails to discover these LE-only devices, although it can still find other Bluetooth devices.

I've tried multiple BLE libraries, including react-native-ble-manager and react-native-ble-plx, but the problem persists. Interestingly, when using nRF Connect on the same Android 12+ devices, the Tags are discovered without any issues, displaying the correct MAC addresses and local names.

I've spent considerable time trying to resolve this issue, including adjusting permissions, scanning settings, and handling advertising data, but haven't found a solution. I'm hoping someone can help me identify what's going wrong.

What I've Tried:

Permissions:

  • Updated AndroidManifest.xml with all necessary permissions.
  • Requested runtime permissions, including BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and ACCESS_FINE_LOCATION.
  • Ensured location services are enabled on the device.

Scanning Code:

  • Removed all filters during scanning to allow all devices to be discovered.
  • Adjusted scanning settings, including allowDuplicates, scanMode, and matchMode.
  • Logged full device objects during scanning to analyze available data.

Libraries:

  • Tried both react-native-ble-manager and react-native-ble-plx to perform scanning.
  • Updated libraries to the latest versions to ensure compatibility with Android 12+.

Testing:

  • Created a minimal app focused solely on scanning for BLE devices.
  • Tested on multiple Android 12+ devices to rule out device-specific issues.
  • Compared app behavior with nRF Connect, which successfully discovers the Eartags.

Permissions in AndroidManifest.xml:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Android 12+ Permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Scanning & Permission Function


const bleManager = new BleManager();

const startScan = async () => {
  try {
    const permissionsGranted = await checkPermissions();
    if (!permissionsGranted) {
      console.log('Permissions not granted');
      return;
    }

    bleManager.startDeviceScan(
      null,
      { allowDuplicates: true },
      (error, device) => {
        if (error) {
          console.error('Scan error:', error);
          return;
        }

        // Log the full device object
        console.log('Discovered device:', JSON.stringify(device, null, 2));

        if (isEartag(device)) {
          console.log('Eartag found:', device.id);
        }
      },
    );

    // Stop scanning after a set duration
    setTimeout(() => {
      bleManager.stopDeviceScan();
      console.log('Scan stopped');
    }, 5000);
  } catch (error) {
    console.error('Scan error:', error);
  }
};

const checkPermissions = async () => {
    try {
      if (Platform.OS === 'ios') {
        return true;
      }
      if (
        Platform.OS === 'android' &&
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
      ) {
        const apiLevel = parseInt(Platform.Version.toString(), 10);

        if (apiLevel < 31) {
          const granted = await PermissionsAndroid.request(
            PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          );
          return granted === PermissionsAndroid.RESULTS.GRANTED;
        }
        if (
          PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN &&
          PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
        ) {
          const result = await PermissionsAndroid.requestMultiple([
            PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
            PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
            PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
          ]);

          return (
            result['android.permission.BLUETOOTH_CONNECT'] ===
              PermissionsAndroid.RESULTS.GRANTED &&
            result['android.permission.BLUETOOTH_SCAN'] ===
              PermissionsAndroid.RESULTS.GRANTED &&
            result['android.permission.ACCESS_FINE_LOCATION'] ===
              PermissionsAndroid.RESULTS.GRANTED
          );
        }
      }
      showErrorToast('Permission have not been granted');
      return false;
    } catch (error) {
      console.error('Error in permission check:', error);
      return false;
    }
  };

Devices that I try to find (nRF Connect on the same device)

nRF Connect Screenshot

Share Improve this question edited Nov 17, 2024 at 18:38 MoritzG asked Nov 17, 2024 at 16:23 MoritzGMoritzG 11 bronze badge 2
  • Welcome to Stack Overflow. To be honest, your question reads like it was written by ChatGPT. However, while your question states that you have requested runtime permissions, your sample code doesn't. Are you sure you've read and understood the Google docs? What does your console log look like when your application is running? – Risto Commented Nov 17, 2024 at 18:16
  • Firstly, thank you very much for your prompt answer. I have reformatted the question, but I didn't generate the content itself. I request the runtime permissions with the function checkPermissions() given in my example. All needed permissions are granted, which we checked multiple times. If required, I will, of course, add the missing function (though I need to check how to edit). Thanks again! – MoritzG Commented Nov 17, 2024 at 18:27
Add a comment  | 

2 Answers 2

Reset to default 0
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" tools:remove="android:usesPermissionFlags" />

Resolved this issue for me and nothing else I found did

You have to add this permission

<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation" />

in the controller :

if (Platform.isAndroid && (await getAndroidVersion()) >= 12) {
  permissions.add(Permission.bluetoothScan);
  permissions.add(Permission.nearbyWifiDevices);
}

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745631971a4637164.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信