定位权限适配
Android 定位权限变更
本文梳理 Android1.0~Android11 定位权限几次重大变更和适配。
版本变更
- Android 6.0(Android 23)之前,在清单文件声明定位权限即可:
ACCESS_COARSE_LOCATION
和ACCESS_FINE_LOCATION
Android 6.0 及以上,新增运行时权限,使用定位的 2 个权限,需要运行时动态申请  Android 10.0,新增后台定位权限,弹窗多了一个选项, Allow all the time
 - Android 11.0 新增仅限这一次授权机制,申请普通定位权限弹窗多了一个选项:Only this time ;普通定位权限和后台定位权限需要分开申请
Android 中的三个定位权限详解
1
2
3
4
5
6
7
8
<!-- Allows an app to access approximate location. 近似定位权限,Api1,如:网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Allows an app to access precise location 精准定位权限,Api1,如:GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Allows an app to access location in the background. 后台定位权限, Api29,Android10新增 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
定位权限分类:
普通定位和后台定位权限
ACCESS_COARSE_LOCATION
和ACCESS_FINE_LOCATION
统称为 普通定位权限ACCESS_BACKGROUND_LOCATION
称为 后台定位权限
网络、GPS 和后台定位权限
- 网络定位权限属于:ACCESS_COARSE_LOCATION
- GPS 定位权限属于:ACCESS_FINE_LOCATION
- 后台定位权限:ACCESS_BACKGROUND_LOCATION
谷歌在 Android10 之后,新增的后台定位权限
ACCESS_BACKGROUND_LOCATION
。后台定位权限,顾名思义,如果 APP 没有获得后台定位权限,当 APP 处在后台时,获取定位会失败。
注意点
后台定位权限针对的是 Android10 及以上系统
在 Android10 及以上的手机,即使 targetSdkVersion 小于 29,如果用户没有主动授权后台定位权限,APP 处在后台也将无法获取定位。 并且,targetSdkVersion
小于 29,申请 普通定位权限 的弹窗有所变化。
APP 的 targetSdkVersion=26
,Android10 的系统。只申请 ACCESS_FINE_LOCATION
权限,弹窗也会有 Allow only while using the app 和 Allow all the time :
 |
Android10 系统同时申请普通定位权限和后台定位权限
申请权限的代码:
1
2
3
4
5
6
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
}
}
 |
如果只请求 Manifest.permission.ACCESS_FINE_LOCATION
权限,只有两个按钮。
 |
Android 11 系统上,将后台定位权限又做了一次调整
targetSdkVersion=android11
时,不能同时申请普通定位权限和后台定位权限。只有成功申请了 普通定位权限,才能申请后台定位权限。
targetSdkVersion=android11
,在 Activity.requestPermissions()
中,同时申请,普通定位权限和后台定位权限,将不会弹窗,直接授权失败。
1
2
3
4
5
6
7
8
// 这次将会调用失败
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// targetSdkVersion=android11,在android11手机上,将直接授权失败
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
}
}
也就是说,如果你想获得后台定位权限,必须弹窗两次:
- 第一次,申请普通定位权限的弹窗。
- 第二次,在用户同意了普通定位权限之后,申请后台定位权限时弹窗。
这里也要千万注意,在没有拿到 普通定位权限的时候,直接申请后台定位权限,将不弹窗直接授权失败。
只有普通定位权限,如何让 APP 在后台时定位?
Android10 以上设备,只有普通定位权限,没有 Activity 在前台时,APP 还能获得定位吗?
通过定位服务。
后台定位服务需要满足 3 个条件:
- APP 至少已获得普通定位权限
- Service 必须是前台服务
foregroundService
- 在
androidmenifest.xml
中必须申明foregroundServiceType
,如下
1
2
3
<service
android:name="com.xxx.notification.SportingNotificationService"
android:foregroundServiceType="location"/>
这样我们即使没有前台 Activity,只要定位服务在后台依然可以获手机定位数据。
注意:定位 Service 有个缺陷,就是这个 Service 必现是前台 Service。也就意味着必须有通知栏。