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

如何获取Android Oreo系统下已连接蓝牙设备的名称

解决Android Oreo获取已连接蓝牙设备名称的问题

我之前在Android 8.0(Oreo)上也碰到过一模一样的坑——那些老的蓝牙设备查询方法要么失效,要么直接抛出IOException: read failed, socket might closed错误。这主要是因为Oreo开始对蓝牙API的权限和访问限制做了调整,老方法已经不适用了。给你两个亲测有效的方案:

方案一:通过BluetoothManager直接获取已连接设备

这是最直接的方式,利用系统提供的BluetoothManager API来获取当前处于连接状态的蓝牙设备,不需要手动操作socket,自然不会触发那个IO错误。

步骤:

  1. 添加权限:在AndroidManifest.xml里声明必要的蓝牙权限(Oreo属于正常权限,无需动态申请):
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  1. 获取已连接设备:通过BluetoothManager获取指定蓝牙Profile的已连接设备,比如音频设备用BluetoothProfile.A2DP或BluetoothProfile.HEADSET,通用设备用BluetoothProfile.GATT:
// 获取BluetoothManager实例
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
// 获取连接中的A2DP设备(比如蓝牙耳机、音箱)
List<BluetoothDevice> connectedAudioDevices = bluetoothManager.getConnectedDevices(BluetoothProfile.A2DP);

// 遍历设备列表获取名称
for (BluetoothDevice device : connectedAudioDevices) {
    String deviceName = device.getName();
    String deviceAddress = device.getAddress();
    // 处理设备信息
}
  1. 监听连接状态(可选):如果getConnectedDevices返回空,可能是设备刚连接还没同步状态,可以注册BluetoothProfile.ServiceListener来监听连接变化:
bluetoothManager.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
    @Override
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        List<BluetoothDevice> connectedDevices = proxy.getConnectedDevices();
        // 处理已连接设备
        bluetoothManager.closeProfileProxy(profile, proxy); // 记得用完关闭代理
    }

    @Override
    public void onServiceDisconnected(int profile) {
        // 服务断开处理
    }
}, BluetoothProfile.A2DP);

方案二:动态注册广播接收器监听连接事件

Oreo限制了隐式广播的静态注册,所以我们需要动态注册广播接收器来监听蓝牙设备的连接动作,一旦设备连接成功,直接从Intent中获取设备信息。

实现代码:

  1. 创建广播接收器:
private BroadcastReceiver bluetoothConnectReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
            // 从Intent中取出已连接的蓝牙设备
            BluetoothDevice connectedDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (connectedDevice != null) {
                String deviceName = connectedDevice.getName();
                // 这里处理设备名称
            }
        }
    }
};
  1. 动态注册/注销接收器:
@Override
protected void onResume() {
    super.onResume();
    // 注册广播接收器,监听设备连接事件
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
    registerReceiver(bluetoothConnectReceiver, filter);
}

@Override
protected void onPause() {
    super.onPause();
    // 记得注销接收器,避免内存泄漏
    unregisterReceiver(bluetoothConnectReceiver);
}

为什么老方法会报错?

那些依赖蓝牙Socket连接获取设备信息的方法,在Oreo开始被严格限制——系统会阻止未授权的Socket访问,尤其是当设备未配对或者App没有足够权限时,就会抛出read failed, socket might closed的错误。上面的两种方案都是利用系统提供的官方API,避开了直接操作Socket的风险,所以能稳定运行。

额外注意事项:

  • 确保设备蓝牙已经开启,可以用BluetoothAdapter.getDefaultAdapter().isEnabled()检查,未开启的话可以通过Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)请求用户打开。
  • 部分设备的getName()可能返回null,这时候可以用getAddress()(蓝牙MAC地址)作为备选标识。

内容的提问来源于stack exchange,提问作者Hossain Ehsani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:57:13