Android 12(API 31)中onRequestPermissionsResult不等待用户输入问题
问题描述
我的应用需请求GPS权限,必须等待用户输入后再执行后续操作。在Android 7.1(API 25)中,onRequestPermissionsResult会在用户完成输入后被调用;但在Android 12(API 31)中,该方法在用户输入前就已被触发,且grantResults始终为{-1, -1, -1}。
权限检查代码如下:
final int PERMISSIONS_REQUEST = 1981; private final String[] PERMISSIONS = new String[] { Manifest.permission.ACCESS_FINE_LOCATION , Manifest.permission.ACCESS_COARSE_LOCATION , Manifest.permission.ACCESS_BACKGROUND_LOCATION }; // permission list //... // onclick login button @Override public void onClick(DialogInterface dialogInterface, int i) { boolean permission = isPermissionGranted(); // check permission is granted if (!permission) setGpsPermission(); // request login when permission is not granted. else // start login when permission is granted. { gpsOn = true; startLogin(); } }
权限请求代码如下:
private boolean isPermissionGranted() { for (String permission : PERMISSIONS) { if (permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION) && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { continue; } final int result = ContextCompat.checkSelfPermission(this, permission); if (PackageManager.PERMISSION_GRANTED != result) { return false; } } return true; } private void setGpsPermission() { // request permission ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSIONS_REQUEST); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) // in Android 12(API 31), grantResults always -1, -1, -1 { case PERMISSIONS_REQUEST : if (grantResults.length > 0 && (grantResults[0] == PackageManager.PERMISSION_GRANTED || grantResults[1] == PackageManager.PERMISSION_GRANTED)) { gpsOn = true; startLogin(); } else { gpsOn = false; startLogin(); } break; } }
版本差异原因
Android 12(API 31)对后台位置权限的请求规则做了严格限制:
- 不能同时请求前台位置权限(
ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION)和后台位置权限(ACCESS_BACKGROUND_LOCATION),必须先获得前台位置权限后,再单独请求后台位置权限 - 当一次性请求包含后台位置权限的权限数组时,系统会直接判定为非法请求,立即触发
onRequestPermissionsResult,且所有权限结果返回-1(PackageManager.PERMISSION_DENIED) - Android 7.1没有该限制,因此可以一次性请求所有权限,等待用户操作后返回结果
修复方案
按照Android 10+的权限规则,分两步请求位置权限:
步骤1:拆分权限请求逻辑
将前台和后台权限拆分,先请求前台权限,用户同意后再请求后台权限:
private final String[] FOREGROUND_PERMISSIONS = new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }; private final String[] BACKGROUND_PERMISSION = new String[]{ Manifest.permission.ACCESS_BACKGROUND_LOCATION }; private static final int PERMISSIONS_REQUEST_BACKGROUND = 1982; // 单独检查前台权限 private boolean isForegroundPermissionGranted() { for (String permission : FOREGROUND_PERMISSIONS) { final int result = ContextCompat.checkSelfPermission(this, permission); if (PackageManager.PERMISSION_GRANTED != result) { return false; } } return true; } // 单独检查后台权限 private boolean isBackgroundPermissionGranted() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { return true; } return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED; } // 修改登录按钮点击逻辑 @Override public void onClick(DialogInterface dialogInterface, int i) { if (!isForegroundPermissionGranted()) { ActivityCompat.requestPermissions(this, FOREGROUND_PERMISSIONS, PERMISSIONS_REQUEST); } else if (!isBackgroundPermissionGranted()) { ActivityCompat.requestPermissions(this, BACKGROUND_PERMISSION, PERMISSIONS_REQUEST_BACKGROUND); } else { gpsOn = true; startLogin(); } } // 修改权限回调处理 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case PERMISSIONS_REQUEST: if (grantResults.length > 0 && (grantResults[0] == PackageManager.PERMISSION_GRANTED || grantResults[1] == PackageManager.PERMISSION_GRANTED)) { // 前台权限获取成功,判断是否需要请求后台权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !isBackgroundPermissionGranted()) { ActivityCompat.requestPermissions(this, BACKGROUND_PERMISSION, PERMISSIONS_REQUEST_BACKGROUND); } else { gpsOn = true; startLogin(); } } else { gpsOn = false; startLogin(); } break; case PERMISSIONS_REQUEST_BACKGROUND: gpsOn = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; startLogin(); break; } }
额外注意事项
- Android 12+中请求后台位置权限时,系统会直接跳转到应用权限设置页面,而非弹出对话框,这是系统强制规则,无法修改
- 确保
AndroidManifest.xml中正确声明权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="33" />
内容的提问来源于stack exchange,提问作者js u
相关产品推荐
相关产品推荐

