2. 蓝牙配对管理

任务说明

本案例实现Android蓝牙配对管理功能,覆盖三个核心能力:主动发起配对(针对已扫描到但未配对的设备)、被动处理配对请求(监听系统配对请求广播并自动确认)、实时显示配对状态。案例基于经典蓝牙(非BLE),使用最小可复现工程完成闭环。

实现方案

整体采用广播接收器+服务组合方式:BondRequestReceiver监听系统配对请求广播,自动调用createBond()确认配对;PairingManager封装发起配对与状态查询逻辑;界面层通过BroadcastReceiver动态监听ACTION_BOND_STATE_CHANGED更新UI。需要说明的是,Android 10及以上系统对隐式广播限制严格,因此配对请求监听采用动态注册方式,且仅适用于API 26-29(Android 8.0-10)作为演示范围;API 29以上系统禁止应用自动确认配对请求,需用户手动确认,本案例代码在该场景下仅能显示配对请求,不能自动确认。

核心代码


// PairingManager.java
public class PairingManager {
    private final BluetoothAdapter adapter;

    public PairingManager() {
        adapter = BluetoothAdapter.getDefaultAdapter();
    }

    // 发起配对(API 19+)
    public boolean pair(BluetoothDevice device) {
        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
            return device.createBond();
        }
        return false;
    }

    // 获取配对状态描述
    public String getBondState(BluetoothDevice device) {
        switch (device.getBondState()) {
            case BluetoothDevice.BOND_BONDED: return "已配对";
            case BluetoothDevice.BOND_BONDING: return "配对中";
            default: return "未配对";
        }
    }
}

// BondRequestReceiver.java(动态注册)
public class BondRequestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // API 26-29 可自动确认;API 30+ 此调用无效,需用户手动确认
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
                try {
                    device.setPin("0000".getBytes());
                    device.setPairingConfirmation(true);
                } catch (Exception ignored) {}
            }
        }
    }
}

// MainActivity.java(关键片段)
public class MainActivity extends AppCompatActivity {
    private BluetoothAdapter adapter;
    private BroadcastReceiver bondReceiver;
    private BroadcastReceiver pairingReceiver;
    private TextView statusView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        statusView = findViewById(R.id.status);
        adapter = BluetoothAdapter.getDefaultAdapter();

        // 动态注册配对请求监听
        pairingReceiver = new BondRequestReceiver();
        IntentFilter pf = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
        registerReceiver(pairingReceiver, pf);

        // 动态注册配对状态变化监听
        bondReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
                String msg = device.getName() + ": " + stateToText(state);
                statusView.setText(msg);
            }
        };
        IntentFilter bf = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        registerReceiver(bondReceiver, bf);

        // 示例:对扫描到的第一个未配对设备发起配对
        findViewById(R.id.btn_pair).setOnClickListener(v -> {
            BluetoothDevice target = findFirstUnbondedDevice();
            if (target != null) {
                new PairingManager().pair(target);
            }
        });
    }

    private BluetoothDevice findFirstUnbondedDevice() {
        for (BluetoothDevice device : adapter.getBondedDevices()) {
            // 实际应从扫描结果获取,此处演示直接使用已配对列表外的设备
        }
        // 演示:通过已知MAC构造设备(需替换为真实扫描结果)
        return adapter.getRemoteDevice("AA:BB:CC:DD:EE:FF");
    }

    private String stateToText(int state) {
        switch (state) {
            case BluetoothDevice.BOND_BONDED: return "配对成功";
            case BluetoothDevice.BOND_BONDING: return "正在配对";
            default: return "未配对";
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(bondReceiver);
        unregisterReceiver(pairingReceiver);
    }
}

落地与验证

依赖与权限:AndroidManifest.xml需声明BLUETOOTH、BLUETOOTH_ADMIN权限(API 30及以下),API 31+需BLUETOOTH_CONNECT运行时权限。

运行方式:真机(API 26-29)安装后,开启蓝牙,点击“发起配对”按钮,观察TextView状态变化。

验证方法:准备另一台可被发现蓝牙设备(如手机),确保目标设备未配对。点击按钮后,观察目标设备是否收到配对请求;本机TextView依次显示“正在配对”→“配对成功”。若目标设备拒绝,则显示“未配对”。

判定标准:目标设备出现配对确认弹窗且本机状态变为“配对成功”,即功能通过。API 30+设备仅验证状态显示逻辑,不验证自动确认。

蓝牙配对管理 - 调用时序与状态流转 MainActivity PairingManager BluetoothDevice pair(device) createBond() true / false ACTION_BOND_STATE_CHANGED setText("配对成功") 状态流转 未配对→配对中→已配对