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

Android蓝牙权限请求对话框不显示问题及异常排查求助

蓝牙权限请求异常排查问题

我已经花了一天时间排查这个问题,还是毫无头绪。查了大量同类问题,试了所有建议,都没用。

我的应用有个设置界面,用户可以在这里开启蓝牙。设置界面会给MainActivity发送Intent,后者会检查安全权限,需要的话就发起权限请求。

我针对SDK 32开发,Manifest配置如下:

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>

在MainActivity里我会检查权限是否已授予:

private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Objects.equals(intent.getAction(), CustomIntent.CHECK_BLUETOOTH_SECURITY_PERMISSION)) {
            int check = ContextCompat.checkSelfPermission( thisActivity, Manifest.permission.BLUETOOTH_CONNECT );
            if ( check == PackageManager.PERMISSION_DENIED )
                getPermission( Manifest.permission.BLUETOOTH_CONNECT, RequestCodes.BT_SECURITY_REQUEST.ordinal() );
        }
    }
};

如果权限没授予就发起请求。我试过旧的权限请求方式:

public void getPermission( String permission, int requestCode ) {
    if ( shouldShowRequestPermissionRationale( permission ) ) {
        // TODO: display a dialog to explain the reason for needing the permission
        Toast.makeText( this, "需要说明权限申请的原因", Toast.LENGTH_LONG ).show();
    } else {
        requestPermissions( new String[]{ permission }, requestCode );
    }
}

我既试过用CompactActivity.requestPermissions,也试过上面直接调用requestPermissions的方式。

同时也试了新的权限请求方式,在onCreate里注册:

activityResultLauncher = registerForActivityResult(
    new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
        @Override
        public void onActivityResult(Map<String, Boolean> result) {
            Log.e("ActivityResultLauncher", ""+result.toString() );
            Boolean areAllGranted = true;
            for ( Boolean b : result.values() ) {
                areAllGranted = areAllGranted && b;
            }
            if ( areAllGranted )
                Log.e( "ActivityResultLauncher","权限申请成功");
            else
                Log.e( "ActivityResultLauncher", "权限申请失败");
        }
    });

然后在getPermission()里调用:

activityResultLauncher.launch(new String[]{
                Manifest.permission.BLUETOOTH_CONNECT
        });

但不管用哪种方式,请求权限的用户对话框都不显示,onPermissionRequestResult直接返回False(也就是拒绝)。LogCat里没任何错误信息(除了我自己加的日志),调试Android库代码也没发现异常。

更新

就在我发布这个问题的时候,我尝试清理了模拟器设备。
清理后第一次运行代码,应用直接崩溃,LogCat里捕获到以下信息:

Attempting to launch an unregistered ActivityResultLauncher with contract
androidx.activity.result.contract.ActivityResultContracts$RequestMultiplePermissions
and input [Ljava.lang.String. You must ensure the
ActivityResultLauncher is registered before calling launch().

我确实是在onCreate里注册的activityResultLauncher,搞不懂为什么提示未注册。而且这个错误只在清理设备文件后第一次运行时出现。

之后我再次启动应用(没改任何代码),这次正常运行,对话框显示了,我也能授予权限。

有人知道这到底是怎么回事吗?


问题分析与解决方案

  • 首次启动崩溃原因:清理模拟器后首次启动时,广播可能在onCreate执行完成前就被触发,此时activityResultLauncher还没完成注册,调用launch()就会抛出未注册的异常。
  • 权限对话框不显示的潜在问题:
    1. 清理前的模拟器可能缓存了权限拒绝状态,系统直接返回拒绝而不弹出对话框;
    2. 广播接收器中使用的thisActivity实例可能存在上下文问题,导致权限请求逻辑失效;
  • 修复建议:
    1. 将activityResultLauncher的注册代码放在onCreate方法最开头,确保在任何回调触发前完成注册;
    2. 在广播接收器中增加判断:若activityResultLauncher未初始化,通过Handler.postDelayed延迟1-2秒再处理权限请求;
    3. 调整设置界面发送广播的时机,确保MainActivity完全启动后再发送Intent;
    4. 测试时直接在应用设置中清除数据,彻底重置权限状态,避免模拟器缓存干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:45:28