android定位权限适配看这篇就够了

12,206

一、前言

本文档的目的是梳理,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 称为 后台定位权限

  1. 网络定位权限属于:ACCESS_COARSE_LOCATION

  2. GPS定位权限属于:ACCESS_FINE_LOCATION

  3. 后台定位权限:ACCESS_BACKGROUND_LOCATION

    谷歌在android10之后,新增的后台定位权限 ACCESS_BACKGROUND_LOCATION。

    后台定位权限,顾名思义,如果APP没有获得后台定位权限,当APP处在后台时,获取定位会失败。

四、 需要特别注意3点:

  1. 后台定位权限(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 appAllow all the time

  2. 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权限,只有两个按钮。

  3. 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个条件:

  1. APP至少已获得普通定位权限

  2. Service必须是前台服务 foregroundService

  3. 在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。也就意味着必须有通知栏。