定位权限适配

Android 定位权限变更

本文梳理 Android1.0~Android11 定位权限几次重大变更和适配。

版本变更

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" />

定位权限分类:

普通定位和后台定位权限

网络、GPS 和后台定位权限

谷歌在 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 :

|300

Android10 系统同时申请普通定位权限和后台定位权限

申请权限的代码:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION), 100)
    }
}

|300

如果只请求 Manifest.permission.ACCESS_FINE_LOCATION 权限,只有两个按钮。

|300

Android 11 系统上,将后台定位权限又做了一次调整

targetSdkVersion=android11 时,不能同时申请普通定位权限和后台定位权限。只有成功申请了 普通定位权限,才能申请后台定位权限。

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 在后台时定位?

Android10 以上设备,只有普通定位权限,没有 Activity 在前台时,APP 还能获得定位吗?

通过定位服务

后台定位服务需要满足 3 个条件:

  1. APP 至少已获得普通定位权限
  2. Service 必须是前台服务 foregroundService
  3. androidmenifest.xml 中必须申明 foregroundServiceType,如下
<service
    android:name="com.xxx.notification.SportingNotificationService"
    android:foregroundServiceType="location"/>

这样我们即使没有前台 Activity,只要定位服务在后台依然可以获手机定位数据。

注意:定位 Service 有个缺陷,就是这个 Service 必现是前台 Service。也就意味着必须有通知栏。