一、前言
本文档的目的是梳理,android1.0~android11定位权限几次重大变更和适配。
如果你正在学习android11、android10、android6定位权限的适配,那么本篇最适合你不过了。
如果你想学习android权限的机制,那么本篇非常适合你,透过局部看全局,定位权限是android权限中非常典型的一个权限。
如果以上都不是,你只是一个路过的android开发,那么轻轻的你来了,点个收藏再轻轻的走。
如果你不是一个android开发,请走开,您来错地方了。
定位权限适配确实坑会比较多,且不易描述,看过很多相关的blog,大都写的比较局限不易懂;
于是大叔自己动手,尝试写一篇通俗易懂且实用blog。
如果我做到了,给个赞,认可下吧。
二、android定位权限机制的几次重大变更
上图是,原生android系统,定位权限申请的几次重大变更。
对于理解如何适配定位权限十分重要。
三、android中的三个定位权限详解
<!-- 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 称为 后台定位权限
-
网络定位权限属于:ACCESS_COARSE_LOCATION
-
GPS定位权限属于:ACCESS_FINE_LOCATION
-
后台定位权限:ACCESS_BACKGROUND_LOCATION
谷歌在android10之后,新增的后台定位权限 ACCESS_BACKGROUND_LOCATION。
后台定位权限,顾名思义,如果APP没有获得后台定位权限,当APP处在后台时,获取定位会失败。
四、 需要特别注意3点:
-
后台定位权限(ACCESS_BACKGROUND_LOCATION)十分敏感,与其他新增的权限不太一样。
理论上,android10 新增的权限,新特性不会作用在 targetSdkVersion小于android10的APP上。
但是:谷歌对后台定位权限做了十分严格的处理。android10的手机上targetSDK小于android10也需要做兼。
但是:谷歌对后台定位权限做了十分严格的处理。android10的手机上targetSDK小于android10也需要做兼。
但是:谷歌对后台定位权限做了十分严格的处理。android10的手机上targetSDK小于android10也需要做兼。
在android10以上的手机,即使targetSdkVersion小于android10,如果用户没有主动授权后台定位权限,APP处在后台也将无法获取定位。
并且,targetSdkVersion小于android10,申请 普通定位权限 的弹窗有所变化。
请注意,上面的弹窗的前两个选项;
请注意,上面的弹窗的前两个选项;
请注意,上面的弹窗的前两个选项;
APP的targetSdkVersion=26,android10的系统。只申请ACCESS_FINE_LOCATION权限:
弹窗也会有 Allow only while using the app 和 Allow all the time :
-
android 10系统上,可以在同一个权限弹窗中同时申请:ACCESS_FINE_LOCATION和 ACCESS_BACKGROUND_LOCATION权限。
如下代码,系统将会弹窗
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()中,同时申请,普通定位权限和后台定位权限,将不会弹窗,直接授权失败。
这里千万要注意,targetSdkVersion=android11,在Activity.requestPermissions()中,同时申请,普通定位权限和后台定位权限,将不会弹窗,直接授权失败。
这里千万要注意,targetSdkVersion=android11,在Activity.requestPermissions()中,同时申请,普通定位权限和后台定位权限,将不会弹窗,直接授权失败。
和第二点同样的代码,这次将会调用失败
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在后台时定位?
android 10以上设备,只有普通定位权限,没有Activity在前台时,APP还能获得定位吗?
答案是肯定的。
通过定位服务。
后台定位服务需要满足3个条件:
APP至少已获得普通定位权限
Service必须是前台服务 foregroundService
在androidmenifest.xml中必须申明foregroundServiceType,;如下
<service android:name="com.vivo.health.v2.notification.SportingNotificationService" android:foregroundServiceType="location"/>
这样我们即使没有前台Activity,只要定位服务在后台依然可以获手机定位数据。
注意:定位Service有个缺陷,就是这个Service必现是前台Service。也就意味着必须有通知栏。
注意:定位Service有个缺陷,就是这个Service必现是前台Service。也就意味着必须有通知栏。
注意:定位Service有个缺陷,就是这个Service必现是前台Service。也就意味着必须有通知栏。