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

API 31环境下使用ActivityResultLauncher实现蓝牙启用时应用崩溃且权限对话框无法弹出的问题求助

看起来你遇到的崩溃大概率是因为ActivityResultLauncher的注册时机不对,或者缺少必要的蓝牙权限导致的。让我一步步帮你解决这个问题:

1. 崩溃的核心原因:registerForActivityResult注册时机错误

registerForActivityResult必须在Activity的onCreate生命周期之前完成注册(比如作为类的成员变量初始化,或者在onCreate方法内部的早期执行)。如果在点击事件、onStart等后续方法中注册,就会抛出IllegalStateException,导致应用崩溃。

看你的代码,如果你是在onCreate内部才注册startForResult,那没问题,但如果是在其他地方(比如检查蓝牙状态的代码块里)注册,那肯定会崩。

2. 必须先申请对应蓝牙权限

不同Android版本对蓝牙操作的权限要求不一样,没有权限的话,不仅可能崩溃,还可能导致权限对话框不显示:

  • Android 12+(API 31):需要BLUETOOTH_CONNECT权限
  • Android 10-11(API 29-30):需要ACCESS_FINE_LOCATION权限(因为扫描蓝牙需要位置权限)
  • Android 9及以下:需要BLUETOOTH和BLUETOOTH_ADMIN权限

先把这些权限添加到你的AndroidManifest.xml中:

<!-- 基础蓝牙功能声明 -->
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />

<!-- Android 12+ 权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />

<!-- Android 10-11 权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />

<!-- Android 9及以下权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="28" />

3. 完整的修复代码示例

我把你的代码重新整理,确保权限申请和蓝牙开启逻辑正确:

public class MainActivity extends AppCompatActivity {
    // 提前注册蓝牙开启的Launcher(作为成员变量,确保在onCreate前初始化)
    private ActivityResultLauncher<Intent> enableBtLauncher;
    // 权限申请的Launcher
    private ActivityResultLauncher<String[]> permissionLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化蓝牙开启的回调
        enableBtLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    if (result.getResultCode() == RESULT_OK) {
                        // 蓝牙成功开启,这里可以连接你的LED灯带了
                        Toast.makeText(this, "蓝牙已开启,准备连接设备", Toast.LENGTH_SHORT).show();
                    } else {
                        // 用户拒绝开启蓝牙
                        Toast.makeText(this, "你拒绝了开启蓝牙,无法控制灯带", Toast.LENGTH_SHORT).show();
                    }
                }
        );

        // 初始化权限申请的回调
        permissionLauncher = registerForActivityResult(
                new ActivityResultContracts.RequestMultiplePermissions(),
                permissions -> {
                    boolean allPermissionsGranted = true;
                    for (boolean isGranted : permissions.values()) {
                        allPermissionsGranted &= isGranted;
                    }
                    if (allPermissionsGranted) {
                        // 权限都拿到了,检查并开启蓝牙
                        checkAndEnableBluetooth();
                    } else {
                        Toast.makeText(this, "需要蓝牙权限才能控制灯带", Toast.LENGTH_SHORT).show();
                    }
                }
        );

        // 先申请权限,再处理蓝牙逻辑
        requestNecessaryPermissions();
    }

    private void requestNecessaryPermissions() {
        List<String> requiredPermissions = new ArrayList<>();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Android 12+ 检查BLUETOOTH_CONNECT权限
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                requiredPermissions.add(Manifest.permission.BLUETOOTH_CONNECT);
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10-11 检查位置权限
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requiredPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
        } else {
            // Android 9及以下 检查蓝牙基础权限
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
                requiredPermissions.add(Manifest.permission.BLUETOOTH);
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) != PackageManager.PERMISSION_GRANTED) {
                requiredPermissions.add(Manifest.permission.BLUETOOTH_ADMIN);
            }
        }

        if (!requiredPermissions.isEmpty()) {
            permissionLauncher.launch(requiredPermissions.toArray(new String[0]));
        } else {
            // 权限已经有了,直接检查蓝牙
            checkAndEnableBluetooth();
        }
    }

    private void checkAndEnableBluetooth() {
        BluetoothManager bluetoothManager = getSystemService(BluetoothManager.class);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

        if (bluetoothAdapter == null) {
            Toast.makeText(this, "你的设备不支持蓝牙,无法控制灯带", Toast.LENGTH_SHORT).show();
            return;
        }

        if (!bluetoothAdapter.isEnabled()) {
            // 启动蓝牙开启对话框
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            enableBtLauncher.launch(enableBtIntent);
        } else {
            Toast.makeText(this, "蓝牙已经开启,开始连接灯带吧", Toast.LENGTH_SHORT).show();
        }
    }
}

关键注意事项

  • 确保registerForActivityResult是在Activity的onCreate方法中或者作为成员变量注册,绝对不能在点击事件等动态逻辑中注册,这是导致崩溃的最常见原因。
  • 先申请权限再开启蓝牙,否则系统可能会阻止你的请求,甚至崩溃。
  • 因为你只需要控制自己的LED灯带,所以不需要处理旧API的兼容问题,上面的代码已经覆盖了现代Android版本的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:43:11