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

Android应用请求定位与录音权限时后台崩溃问题排查

问题分析与解决方案

从你的代码和真机崩溃的表现来看,核心问题主要有两个,咱们一步步梳理:

1. 连续发起两次权限请求触发系统状态冲突

Android 6.0+的权限请求是异步处理的,当你第一次调用requestPermissions弹出定位权限弹窗后,系统正处于处理该请求的状态中,你紧接着又发起录音权限的请求,这种连续触发的方式在真机的权限管理机制下会导致状态混乱,进而引发崩溃(模拟器的权限校验逻辑相对宽松,所以没暴露这个问题)。

Android官方明确建议:一次性请求所有所需的相关权限,而非分多次发起请求。

2. onRequestPermissionsResult分支缺少break导致逻辑异常

你的case 1处理完定位权限的逻辑后没有添加break,会让代码直接"穿透"到case 2的逻辑里。此时grantResults对应的是定位权限的结果,你却把它赋值给permissionToRecordAccepted,这会造成逻辑错误——虽然这不一定是崩溃的直接原因,但也是严重的代码隐患,可能引发后续其他异常。


修复后的代码示例

权限请求代码优化

把两个权限合并成一次请求发起:

if (Build.VERSION.SDK_INT >= 23) {
    // 收集所有未授予的权限
    List<String> pendingPermissions = new ArrayList<>();
    
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        pendingPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        pendingPermissions.add(Manifest.permission.RECORD_AUDIO);
    }
    
    // 存在未授权权限时,一次性发起请求
    if (!pendingPermissions.isEmpty()) {
        ActivityCompat.requestPermissions(this, pendingPermissions.toArray(new String[0]), 100); // 使用统一的请求码
    } else {
        // 所有权限已授予,执行业务逻辑
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListener);
        permissionToRecordAccepted = true;
    }
}

onRequestPermissionsResult方法修复

补充break,同时处理统一请求后的权限结果:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100) {
        boolean isLocationGranted = false;
        boolean isRecordGranted = false;
        
        // 遍历权限结果,逐个判断授权状态
        for (int i = 0; i < permissions.length; i++) {
            if (Manifest.permission.ACCESS_FINE_LOCATION.equals(permissions[i])) {
                isLocationGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
            } else if (Manifest.permission.RECORD_AUDIO.equals(permissions[i])) {
                isRecordGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
                permissionToRecordAccepted = isRecordGranted;
            }
        }
        
        // 定位权限授权成功后启动定位更新
        if (isLocationGranted && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListener);
        }
        
        // 可选:添加权限被拒绝后的提示逻辑,引导用户去设置页开启权限
    }
}

额外建议

  • 当权限被用户拒绝时,最好弹出友好提示,说明该权限对功能的必要性,引导用户前往应用设置页手动开启。
  • 可以考虑使用成熟的第三方权限库(如RxPermissions、EasyPermissions)来简化权限请求的流程,减少手动管理带来的出错概率。

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

火山引擎 最新活动