Android位置权限异常求助:弹窗不稳定+Android10无始终允许选项
问题分析与解决方案
问题1:位置权限请求弹窗偶尔出现
你的代码中多次单独调用requestPermissions,而Android系统同一时间只能显示一个权限请求弹窗。当短信权限和位置权限的请求同时触发时,后发起的请求会覆盖先发起的,导致部分位置权限的请求被“吞掉”,表现为弹窗偶尔出现。
所有权限请求应该合并为一次调用,避免系统处理冲突。
问题2:Android 10(API 29)无“始终允许”选项
Android Q(API 29)对ACCESS_BACKGROUND_LOCATION的申请有严格要求:
- 必须先获得前台位置权限(
ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION)的授权(用户选择“使用期间允许”); - 不能单独请求
ACCESS_BACKGROUND_LOCATION,需要在用户已授予前台权限的前提下,再发起后台权限请求,此时弹窗才会显示“始终允许”选项。
你的代码中直接单独请求ACCESS_BACKGROUND_LOCATION,不符合系统权限申请逻辑,因此不会出现“始终允许”选项。
修正后的代码示例
步骤1:合并前台权限请求(短信+位置前台权限)
// 合并需要申请的前台权限列表 List<String> requestPermissions = new ArrayList<>(); // 短信权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) { requestPermissions.add(Manifest.permission.RECEIVE_SMS); } if (ActivityCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { requestPermissions.add(Manifest.permission.SEND_SMS); } // 前台位置权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); } // 发起前台权限请求 if (!requestPermissions.isEmpty()) { ActivityCompat.requestPermissions(this, requestPermissions.toArray(new String[0]), Utils.PERMISSION_REQUEST_FOREGROUND); // 自定义请求码 }
步骤2:在权限回调中请求后台位置权限
重写onRequestPermissionsResult方法,在前台权限授予后,再请求后台位置权限:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == Utils.PERMISSION_REQUEST_FOREGROUND) { // 检查前台位置权限是否已授予 boolean hasFineLocation = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; boolean hasCoarseLocation = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && (hasFineLocation || hasCoarseLocation)) { // 前台权限已授予,请求后台位置权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, Utils.PERMISSION_ACCESS_BACKGROUND_LOCATION); } } } }
额外注意事项
- 申请权限前,建议先向用户说明权限用途(比如弹窗提示为什么需要位置权限),提高用户授权意愿;
- 避免在App启动时一次性请求过多权限,可根据功能触发时机按需申请;
- 对于Android 11+(API 30),后台权限的申请逻辑类似,但系统会直接跳转到权限设置页,而非弹窗。
内容的提问来源于stack exchange,提问作者Alessandro
相关产品推荐
相关产品推荐

