You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android调用monitorCharacteristicForService致BLE断开,求手动创建Bond方案

手动创建BLE设备Bond的实现思路(React Native Android)

Hey there! Let’s tackle this BLE bonding issue you’re facing. That error code 19 (UNKNOWN) often pops up when the device isn’t properly bonded, so manually initiating the bond makes total sense. Since react-native-ble-plx doesn’t expose a direct API for this, we’ll need to bridge to native Android code to handle the system-level bonding process. Here’s a detailed breakdown:

1. Understand Android BLE Bond Basics

On Android, BLE devices have three bond states: BOND_NONE (unpaired), BOND_BONDING (in progress), and BOND_BONDED (paired). Bonding is handled by the system, and we trigger it via the native BluetoothDevice.createBond() method—something we can’t call directly from React Native, hence the need for a custom bridge.

2. Build a Native Android Bridge Module

We’ll create a custom native module to expose the bonding functionality to our React Native code:

Step 2.1 Create the Bond Module Class

In your project’s android/app/src/main/java/[your-package-name]/ folder, add a new class BLEBondModule.java:

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;

public class BLEBondModule extends ReactContextBaseJavaModule {
    private BluetoothManager bluetoothManager;

    public BLEBondModule(ReactApplicationContext reactContext) {
        super(reactContext);
        bluetoothManager = (BluetoothManager) reactContext.getSystemService(Context.BLUETOOTH_SERVICE);
    }

    @Override
    public String getName() {
        return "BLEBondModule";
    }

    @ReactMethod
    public void createBond(String deviceAddress, Promise promise) {
        BluetoothDevice device = bluetoothManager.getAdapter().getRemoteDevice(deviceAddress);
        if (device == null) {
            promise.reject("DEVICE_NOT_FOUND", "Cannot locate BLE device with address: " + deviceAddress);
            return;
        }

        int bondState = device.getBondState();
        if (bondState == BluetoothDevice.BOND_BONDED) {
            promise.resolve("Device is already bonded");
            return;
        } else if (bondState == BluetoothDevice.BOND_BONDING) {
            promise.reject("BONDING_IN_PROGRESS", "Device is already pairing");
            return;
        }

        // Initiate system bonding
        boolean success = device.createBond();
        if (success) {
            promise.resolve("Bonding started successfully");
        } else {
            promise.reject("BOND_FAILED", "Failed to start bonding process");
        }
    }
}

Step 2.2 Register the Module

Create a package class BLEBondPackage.java to register the module with React Native:

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BLEBondPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new BLEBondModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Then add this package to MainApplication.java:

@Override
protected List<ReactPackage> getPackages() {
    List<ReactPackage> packages = new PackageList(this).getPackages();
    // Add our custom bond package
    packages.add(new BLEBondPackage());
    return packages;
}

3. Call the Bond Method from React Native

Now you can trigger bonding from your JS code—ideally before connecting to the device, or right after connecting:

import { NativeModules } from 'react-native';
const { BLEBondModule } = NativeModules;

const initiateDeviceBond = async (deviceAddress) => {
  try {
    const response = await BLEBondModule.createBond(deviceAddress);
    console.log(response);
    // Wait for bonding to complete (we'll add state listening next)
    await waitForBondCompletion(deviceAddress);
    // Now proceed with connect() or monitorCharacteristicForService()
  } catch (error) {
    console.error('Bonding failed:', error);
  }
};

To confirm when bonding finishes, we can listen to Android’s system broadcast for bond state changes and relay that to React Native:

Add this broadcast receiver to BLEBondModule.java:

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.modules.core.DeviceEventManagerModule;

private BroadcastReceiver bondStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int prevState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
            int currentState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);

            WritableMap eventData = Arguments.createMap();
            eventData.putString("deviceAddress", device.getAddress());
            eventData.putInt("previousBondState", prevState);
            eventData.putInt("currentBondState", currentState);

            // Send event to React Native
            getReactApplicationContext()
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("bondStateUpdated", eventData);
        }
    }
};

// Register receiver on module init
@Override
public void initialize() {
    super.initialize();
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    getReactApplicationContext().registerReceiver(bondStateReceiver, filter);
}

// Unregister on module destroy
@Override
public void onCatalystInstanceDestroy() {
    super.onCatalystInstanceDestroy();
    getReactApplicationContext().unregisterReceiver(bondStateReceiver);
}

Then listen for the event in JS:

import { NativeEventEmitter } from 'react-native';

const bondEventEmitter = new NativeEventEmitter(NativeModules.BLEBondModule);
const bondSubscription = bondEventEmitter.addListener('bondStateUpdated', (event) => {
  console.log('Bond state changed:', event);
  // BOND_BONDED = 12, BOND_NONE = 10, BOND_BONDING = 11
  if (event.currentBondState === 12) {
    console.log('Device bonded successfully!');
    // Now safely call monitorCharacteristicForService
  } else if (event.currentBondState === 10) {
    console.log('Bonding failed or was cancelled');
  }
});

// Don't forget to clean up the subscription when your component unmounts
// useEffect(() => {
//   return () => bondSubscription.remove();
// }, []);

5. Update Permissions

Make sure your AndroidManifest.xml has all required permissions:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- For Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Also, remember to request location permissions dynamically on Android 6.0+—BLE scanning requires it.

6. Best Practices with react-native-ble-plx

  • Always ensure the device is bonded before calling monitorCharacteristicForService—this should resolve that error code 19 issue.
  • If your device requires a PIN, Android will automatically show a system dialog for the user to enter it—no extra code needed.

内容的提问来源于stack exchange,提问作者Jatin Garg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 20:38:15