由于现在位置信息变为敏感数据,因此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就有了后台使用位置的权限了。