You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 12环境下BLE应用中BluetoothDevice.getName()方法返回null问题求助

Android 12下BLE设备名称返回null的解决方案

我之前在开发BLE应用时也遇到过一模一样的问题——Android 12以下版本正常,升级后连接成功但BluetoothDevice.getName()始终返回null,即使权限都配置到位了。结合官方文档和实际调试经验,给你几个可行的解决方向:

1. 修正BLUETOOTH_SCAN权限的声明

Android 12+对BLE扫描权限做了更严格的限制,即使你的应用不需要位置信息,也必须明确声明这一点,否则系统会默认限制设备信息的获取。修改Manifest中的BLUETOOTH_SCAN权限:

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

如果你的应用确实需要通过BLE扫描获取位置,那要确保ACCESS_FINE_LOCATION的运行时权限也已正确申请。

2. 在扫描阶段缓存设备名称

Android 12+对连接后获取设备名称做了限制,建议在扫描回调中提前缓存设备的地址与名称映射,后续用地址匹配获取名称:

// 全局缓存设备地址和名称的映射
private Map<String, String> deviceNameCache = new HashMap<>();

// 扫描回调中缓存名称
@Override
public void onScanResult(int callbackType, ScanResult result) {
    super.onScanResult(callbackType, result);
    BluetoothDevice device = result.getDevice();
    if (device.getName() != null) {
        deviceNameCache.put(device.getAddress(), device.getName());
    }
}

// 在onCharacteristicChanged中使用缓存的名称
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    super.onCharacteristicChanged(gatt, characteristic);
    String deviceAddress = gatt.getDevice().getAddress();
    // 优先从缓存取名称,取不到用地址兜底
    String deviceName = deviceNameCache.getOrDefault(deviceAddress, deviceAddress);
    
    Log.e("prepareCallSMSData", "onCharacteristicChanged BluetoothGatt " + deviceName);
    Log.e("prepareCallSMSData", "device to app : " + MokoUtils.bytesToHexString(characteristic.getValue()));
    mMokoResponseCallback.onCharacteristicChanged(deviceName, characteristic, characteristic.getValue());
}

3. 主动读取GATT服务中的设备名称特征

部分BLE设备会在GATT服务中广播设备名称(通常是0x1800服务下的0x2A00特征),可以在连接成功后主动读取这个特征来获取名称:

@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    super.onConnectionStateChange(gatt, status, newState);
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        // 连接成功后发现服务
        gatt.discoverServices();
    }
}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    super.onServicesDiscovered(gatt, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // 获取通用访问服务(0x1800)
        BluetoothGattService service = gatt.getService(UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"));
        if (service != null) {
            // 获取设备名称特征(0x2A00)
            BluetoothGattCharacteristic nameChar = service.getCharacteristic(UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb"));
            if (nameChar != null) {
                // 读取特征值
                gatt.readCharacteristic(nameChar);
            }
        }
    }
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    super.onCharacteristicRead(gatt, characteristic, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // 解析设备名称并缓存
        String deviceName = new String(characteristic.getValue());
        deviceNameCache.put(gatt.getDevice().getAddress(), deviceName);
    }
}

4. 检查BLE设备的固件设置

有些BLE设备在建立连接后会停止广播设备名称,导致系统无法获取。可以确认设备固件是否有相关配置,或者尝试在连接后重新触发一次扫描(注意Android 12+扫描需要权限)。

内容的提问来源于stack exchange,提问作者Rajesh android developer

火山引擎 最新活动