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

Android 13启动时已连蓝牙耳机触发BLUETOOTH_CONNECT权限异常求助

问题分析

从异常信息和场景来看,核心问题是Android 13下,应用启动时已连接蓝牙耳机的场景中,在权限未完成授予前就调用了蓝牙相关API,触发了BLUETOOTH_CONNECT权限检查失败。

具体原因:

  1. 你的权限请求逻辑存在错误:判断条件使用&&,意味着只有当BLUETOOTH_SCAN和BLUETOOTH_CONNECT两个权限都未授予时才发起请求,只要其中一个已授予就会跳过请求,可能导致权限缺失。
  2. 应用启动阶段(比如LoginActivity的onCreate)在权限请求完成前,就执行了访问蓝牙设备的操作(比如调用getConnectedDevicesWithAttribution),此时权限尚未授予,直接触发SecurityException。
  3. Android 13中BLUETOOTH_CONNECT属于危险权限,必须用户主动授予后才能调用蓝牙连接类API,低版本系统权限机制不同所以无此问题。
解决方案

1. 修正清单文件权限配置

为旧版本权限添加maxSdkVersion,避免Android 13及以上系统冗余处理:

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

2. 修复权限请求逻辑

调整权限数组

Android 13不需要ACCESS_FINE_LOCATION(已通过neverForLocation标记跳过位置关联),也不需要旧的BLUETOOTH/BLUETOOTH_ADMIN权限:

@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
private static final String[] PERMISSIONS_BLUETOOTH_33 = {
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT
};

private static final String[] PERMISSIONS_BLUETOOTH = {
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT,
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADVERTISE,
        Manifest.permission.BLUETOOTH_ADMIN
};

private String[] getBluetoothPermissions() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU 
        ? PERMISSIONS_BLUETOOTH_33 
        : PERMISSIONS_BLUETOOTH;
}

修正权限检查逻辑

将判断条件从&&改为||,只要任一权限未授予就发起请求,并将蓝牙操作延迟到权限授予后执行:

private void checkPermissions() {
    boolean hasScan = ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED;
    boolean hasConnect = ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;

    if (!hasScan || !hasConnect) {
        ActivityCompat.requestPermissions(this, getBluetoothPermissions(), 1);
    } else {
        // 权限已授予,执行蓝牙初始化逻辑
        initBluetoothOperations();
    }
}

// 处理权限请求结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            initBluetoothOperations();
        } else {
            Toast.makeText(this, "蓝牙权限未授予,无法使用蓝牙耳机功能", Toast.LENGTH_SHORT).show();
            // 可添加权限引导逻辑
        }
    }
}

// 所有蓝牙相关操作统一放到这里执行
private void initBluetoothOperations() {
    // 示例:获取已连接的蓝牙耳机
    BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    List<BluetoothDevice> connectedHeadphones = bluetoothManager.getConnectedDevices(BluetoothProfile.HEADSET);
    // 后续业务逻辑处理
}

3. 关键注意事项

  • 确保所有蓝牙相关操作(包括获取已连接设备、绑定蓝牙服务等)都在initBluetoothOperations中执行,禁止在权限授予前调用任何蓝牙API。
  • 检查Application类或其他早期生命周期组件,避免在这些地方提前执行蓝牙操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:30:58