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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:35:35