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




