Flutter SDK 31+已授权仍报MISSING_PERMISSIONS问题求助
解决SDK 31+读取通话记录权限缺失问题
针对你遇到的SDK 31+真机上出现MISSING_PERMISSIONS错误的问题,核心原因是Android 12(API 31)及以上版本对通话记录相关权限的申请逻辑和权限范围做了调整,以下是具体解决步骤:
1. 修正AndroidManifest权限声明
确保Manifest中添加了SDK 31+所需的完整权限,除了原有权限外,需补充READ_PHONE_NUMBERS权限:
<uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- Android 12+ 新增必填权限 --> <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
注意检查是否误加了android:maxSdkVersion属性限制权限生效范围,避免SDK 31+版本无法获取权限。
2. 适配动态权限申请逻辑
Android 12+对敏感权限的申请要求更严格,需根据系统版本动态调整申请的权限列表:
- 对于SDK 31及以上版本,申请
READ_CALL_LOG+READ_PHONE_NUMBERS - 低于SDK 31版本,保持原有
READ_CALL_LOG+READ_PHONE_STATE的申请组合
推荐使用ActivityResultContracts.RequestMultiplePermissions来处理权限申请(替代旧的onRequestPermissionsResult),示例代码如下:
// 注册权限申请回调 private final ActivityResultLauncher<String[]> permissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> { boolean allGranted = true; for (Boolean granted : result.values()) { allGranted &= granted; } if (allGranted) { // 权限全部授予,执行通话记录读取逻辑 loadCallLogs(); } else { // 权限被拒绝,引导用户到设置页开启 showPermissionGuide(); } }); // 发起权限申请 private void requestCallPermissions() { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { permissions = new String[]{Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_PHONE_NUMBERS}; } else { permissions = new String[]{Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_PHONE_STATE}; } permissionLauncher.launch(permissions); }
3. 完善权限检查逻辑
在读取通话记录前,必须检查所有必要权限是否已授予,适配不同系统版本的权限检查逻辑:
private boolean hasRequiredPermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED; } else { return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED; } }
4. 处理权限拒绝后的场景
如果用户拒绝权限后再次申请,Android 12+系统可能不再弹出权限申请弹窗,此时需要引导用户前往应用设置页面手动开启权限:
private void showPermissionGuide() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("权限需要") .setMessage("需要开启通话记录相关权限才能正常使用功能,请前往设置页开启") .setPositiveButton("去设置", (dialog, which) -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); }) .setNegativeButton("取消", null) .show(); }
另外,需确保应用的targetSdkVersion设置为31或更高,编译SDK版本也对应匹配,否则可能触发系统的权限兼容性限制。
内容的提问来源于stack exchange,提问作者alper
相关产品推荐
相关产品推荐

