You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 11后台定位权限重复弹窗问题求助(附代码)

Android 11 后台定位权限重复弹窗问题解决

问题根源

在Android 11中,用户选择「仅允许本次」临时授权后台定位后,应用重启时权限状态会重置为未授权。原代码仅通过checkSelfPermission判断权限状态,未区分用户是否已做出过权限选择,导致每次启动都会触发权限申请,甚至直接跳转至设置页面,造成重复弹窗困扰。

解决方案

通过以下调整优化权限申请逻辑,避免无意义的重复弹窗:

  • 记录用户权限操作状态:用SharedPreferences记录用户是否已处理过权限请求,避免每次启动都触发申请流程。
  • 精准判断权限申请时机:结合shouldShowRequestPermissionRationale和权限状态,仅当用户未明确拒绝权限(需引导说明)时,才弹出权限申请弹窗;若用户已做出过选择(包括临时授权后重启),则不再主动触发申请,除非后续功能需要时再提示。
  • 优化权限申请流程:确保前台定位权限为永久授权(「仅在使用应用时允许」)后,再请求后台定位权限,避免临时授权状态下的无效申请。

修改后的代码

private SharedPreferences permissionPrefs;
private static final String PREF_KEY_LOCATION_PERMISSION_HANDLED = "location_permission_handled";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    
    permissionPrefs = getSharedPreferences("app_permissions", MODE_PRIVATE);
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        checkLocationPermissions();
    }
}

private void checkLocationPermissions() {
    boolean hasFineLocation = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
    boolean hasBackgroundLocation = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED;
    
    if (!hasFineLocation) {
        boolean needRequest = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) 
                || !permissionPrefs.getBoolean(PREF_KEY_LOCATION_PERMISSION_HANDLED, false);
        
        if (needRequest) {
            askForLocationPermission();
        }
    } else if (!hasBackgroundLocation) {
        boolean needRequest = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) 
                || !permissionPrefs.getBoolean(PREF_KEY_LOCATION_PERMISSION_HANDLED, false);
        
        if (needRequest) {
            askPermissionForBackgroundUsage();
        }
    }
}

private void askForLocationPermission() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
        new AlertDialog.Builder(this)
                .setTitle("需要权限")
                .setMessage("应用需要定位权限以提供相关功能")
                .setPositiveButton("确定", (dialog, which) -> {
                    ActivityCompat.requestPermissions(LoginActivity.this,
                            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
                            101);
                })
                .setNegativeButton("取消", (dialog, which) -> {
                    permissionPrefs.edit().putBoolean(PREF_KEY_LOCATION_PERMISSION_HANDLED, true).apply();
                })
                .create().show();
    } else {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
                101);
    }
}

private void askPermissionForBackgroundUsage() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
        new AlertDialog.Builder(this)
                .setTitle("需要后台定位权限")
                .setMessage("应用需要后台定位权限以持续提供服务,请在下一步选择「允许所有时间」")
                .setPositiveButton("确定", (dialog, which) -> {
                    ActivityCompat.requestPermissions(LoginActivity.this,
                            new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                            101);
                })
                .setNegativeButton("取消", (dialog, which) -> {
                    permissionPrefs.edit().putBoolean(PREF_KEY_LOCATION_PERMISSION_HANDLED, true).apply();
                })
                .create().show();
    } else {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
                101);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 101) {
        permissionPrefs.edit().putBoolean(PREF_KEY_LOCATION_PERMISSION_HANDLED, true).apply();
        
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                checkLocationPermissions();
            }
        }
    }
}

关键说明

  • 状态记录:通过SharedPreferences标记用户是否已处理过权限请求,避免重启后重复触发申请。
  • 申请时机控制:仅当shouldShowRequestPermissionRationale返回true(用户未彻底拒绝,需引导)或用户从未处理过权限时,才弹出申请弹窗。
  • 权限流程衔接:在权限申请结果回调中更新状态,并继续检查后续权限,确保流程完整。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:30:44