Android 位置权限的变化以及适配方案

444 阅读3分钟

由于现在位置信息变为敏感数据,因此Android限制的它的使用,尤其在APP后台。在Android 9之前,位置权限还没有按前后台分离,APP在前台和后台使用相同的资源。 但是,Google开始意识到一些APP滥用此类数据,于是决定按照前台和后台分离资源的方式,增加一些层级来保护用户的位置信息数据。 对于Android开发者来说,这对我们在APP中请求位置权限增加了一些额外的工作。 在详细介绍前,现在看看在最近几个Android版本中的更改日志

  • Android 8 中:处于后台的应用,每小时只能检索几次用户的位置。
  • Android 10 之前:位置权限是一个单一资源,应用只需一次授权就可以到处使用,随时使用(前台和后台)。
  • Android 10 中:后台位置变成一个独立资源,应用程序除了前台请求外,还必须明确此权限。
  • Android 11 中:增加了单次位置信息访问权限,并更改了用户授予后台位置信息访问权限的方式。无法与其他人同时请求后台位置权限,应用必须单独请求,此外,请求此权限不会像其他权限一样立即弹出系统权限框提示用户,而是需要自定义弹框,将用户带到/Settings页面/Location权限会话,以便用户可以更新权限级别。

根据上面的这些变化,我们必须根据不同的系统版本处理位置权限的请求,这里有3种不同场景:

Android 10 之前

位置权限只需请求一次,处于前台和后台的APP都可以使用。

String[] permissions = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION};

@Target(28)
private void checkLocationPermissionAPI28(int locationRequestCode){
 
    if(!checkSinglePermission(permissions[0]) || !checkSinglePermission[permissions[1]]){
        requestPermissions(permissions, locationRequestCode);
    }
}

 private boolean checkSinglePermission(String permission){
    return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
 } 

可以看到在这些版本中,用于只有2个选项:拒绝 或 允许

Android 10

在这个版本中,增加了ACCESS_BACKGROUND_LOCATION,你可以请求此权限在同时获得前台和后台的权限,像下面这样:

String[] permissions = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION,
    Manifest.permission.ACCESS_BACKGROUND_LOCATION};
    
@Target(29)
private void checkLocationPermissionAPI29(int locationRequestCode){
    if(checkSinglePermission(permissions[0])||checkSinglePermission(permissions[1])||checkSinglePermission(permissions[2])) 
        return;
    requestPermissions(permissions,locationRequestCode);
}

 private boolean checkSinglePermission(String permission){
    return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
 } 

同样,如果请求前台权限(ACCESS_COARSE_LOCATION 或者 ACCESS_FINE_LOCATION),则Android操作系统会自动将后台权限(ACCESS_BACKGROUND_LOCATION)添加到请求中。它类似与uses-permission声明,无论是ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION被声明,ACCESS_BACKGROUND_LOCATION将在安装过程中被添加。 可以很明显看到下图,用户现在有多个选择:

  • 后台(随时)
  • 前台(仅使用APP期间)
  • 拒绝

Android 11

除上述内容外,开发人员还需要增加其他一些步骤。 这里有2中场景,第一种情况是当仅请求前台权限,在这种情况下,我们通常使用ACCESS_FINE_LOCATION 或者 ACCESS_COARSE_LOCATION,但是,请求授权的弹窗和以前的略有不同,在Android 11 中 Google增加了一个可选项:仅限这一次

请注意,即是将ACCESS_BACKGROUND_LOCATION添加到要请求的权限列表中,系统也将忽略它。

第二种情况是:应用也需要后台权限,为此,必须准备自己的对话框,并使用明确的消息来说明后台位置的使用。

当用户同意后,将它引导到应用的设置页面,那里可以选择他想授予的权限等级

实例如下:


@TargetApi(30)
private void checkBackgroundLocationPermissionAPI30(){
    if(checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
        return
    new AlertDialog.Builder(this)
        .setTitle("申请后台位置权限")
        .setMessage("我需要你的后台位置权限,立刻给我!!!")
        .setPositiveButton("立刻去",(dialog, which)->{
            // 跳转 Settings 页面
        })
        .setNegativeButton("就不去",(dialog, which)->{
            dialog.dismiss();
        })
        .create()
        .show();
}

如图所示:

如你所见,Android 11 中,我们有4个权限等级用于位置信息。 当用户选择始终允许(Allow all the time),APP就有了后台使用位置的权限了。