MoritzG
MoritzG

Reputation: 1

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

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:

Scanning Code:

Libraries:

Testing:

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

Upvotes: 0

Views: 138

Answers (1)

Shawn Reardon
Shawn Reardon

Reputation: 1

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

Resolved this issue for me and nothing else I found did

Upvotes: 0

Related Questions