Android Q适配(2)-------定位篇

前言

本来是准备第二篇直接写AndroidQ的存储权限等方面的修改和适配的,但是可能是由于我学艺不精,在实践中发现AndroidQ表现的跟Google官方文档描述出入较大,所以目前还在摸索中,那么第二篇文章就先写AndroidQ关于定位权限的修改了。本文分为2个部分,改动解决方案和实践代码。

改动

AndroidQ新引入了后台定位权限,是危险权限需要代码动态申请

<!--允许App在后台获得位置信息-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

这个权限必须配合下面两个权限使用,单独写没有任何效果

<!--允许获得精确的GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--允许获得粗略的基站网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

Google加入这个权限,意在将App是否能定位的权利分为前台和后台分别交给用户决定,减少App在后台静默定位的可能性,减少用户的个人信息的泄露。

此项改动将会针对所有版本编译的App生效,所以你无法通过修改targetSdkVersion来回避这个问题,由于老版本sdk没有对应的后台定位权限,如果不对AndroidQ进行适配,那么反而会造成无法正常运行的问题。

适配

1、权限申请

首先根据自己app的实际需求设置对应的权限,如果不是地图导航软件,运动计步软件这种需要持续进行定位的情况,其实大多数应用根本就不用申请后台定位这个权限,请工程师不要滥用权限。

首先要在AndroidManifest.xml文件中写入对应的权限。

<manifest>
    <!--允许获得精确的GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!--允许获得粗略的基站网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <!--允许App在后台获得位置信息-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
</manifest>

在申请后台定位权限以前,用户必须先同意定位权限,否则后台定位权限将会被自动拒绝,所以如果你是一条一条申请权限的逻辑的话,需要先申请定位权限。

//android.permission.ACCESS_FINE_LOCATION或android.permission.ACCESS_COARSE_LOCATION
//任选其一申请定位权限
ActivityCompat.requestPermissions(this, 
new String[] {Manifest.permission.ACCESS_COARSE_LOCATION},
your-permission-request-code);

你会看到这样的申请界面

《Android Q适配(2)-------定位篇》 前台定位权限申请界面

在确保用户同意了此权限以后,再申请后台权限

//申请后台权限
ActivityCompat.requestPermissions(this, 
new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION},
your-permission-request-code);

你会看到后台请求的说明

《Android Q适配(2)-------定位篇》 后台定位权限申请界面

得到这两个权限以后,既可以像老版本一样完成完全得到定位相关的权限了

当然你可以直接申请多个权限,AndroidQ对多个相同的权限组申请会合并成一个申请,所以我们也可以这么写

//同时申请所有定位权限,顺序不分先后
ActivityCompat.requestPermissions(this, 
new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION},
your-permission-request-code);

这样就会得到3个选项的权限请求

《Android Q适配(2)-------定位篇》 合并定位权限请求界面

这里需要注意的是,如果是老版本的app,点击仅在使用该应用期间允许,系统会认为你拥有全部定位权限,回调会提示得到所有权限,但是事实上你并不能后台定位,也不可以再次申请这个权限。

如果是AndroidQ适配以后,点击仅在使用该应用期间允许,系统会认为你允许了前台定位权限,但是拒绝了后台定位权限,所以这次请求回调会提示失败,有权限未通过。下次再执行这个申请时,系统会只申请后台定位权限。

到这一步适配权限就全部讲完了,那么下一步咱们就来浅谈一下具体的情景适配方法

应用场景

1、前台定位,不需要后台定位权限

2、后台定位,需要对应权限

总体来说跟以前的方法是一样的,所以这里只讨论由于后台定位权限的加入,引发的一种新的应用场景—-没有后台定位权限,依然进行类后台定位。

看了上文,肯定有同学有疑问,就是如果我没有申请后台定位权限,是不是我就真的无法做到关掉界面得到定位信息呢?事实是,依然可以。或者我把这个需求换个说法,就是用户选择拒绝我的App后台定位权限,我如何来继续完成诸如导航,计步这种需要关掉界面后依然在持续定位的需求呢。答案显而易见:foregroundService(前台服务)

前台服务就算你把app放到后台了,当前没有Activity可见,系统依然可以认为你是在前台状态,所以不需要申请后台定位权限,也可以继续进行定位。具体做法改动如下

     <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        ...
    </service>

首先在AndroidManifest.xml里注册service,AndroidQ新加入了foregroundServiceType这个属性,请选择”location”

在启动前台服务之前,请确保您的应用仍可访问用户的位置信息:

boolean permissionAccessCoarseLocationApproved =
        ActivityCompat.checkSelfPermission(this,
            permission.ACCESS_COARSE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED;

    if (permissionAccessCoarseLocationApproved) {
        // App有前台定位权限. 启动你的有"location"的前台服务
    } else {
       // 没有权限,发起前台定位权限申请
       ActivityCompat.requestPermissions(this, new String[] {
            Manifest.permission.ACCESS_COARSE_LOCATION},
           your-permission-request-code);
    }

打开对应的Service后,进行对应的定位操作就可以了。

后台定位的场景代码这里也翻译一下贴出来给大家,

boolean permissionAccessCoarseLocationApproved =
        ActivityCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION)
            == PackageManager.PERMISSION_GRANTED;

    if (permissionAccessCoarseLocationApproved) {
       boolean backgroundLocationPermissionApproved =
               ActivityCompat.checkSelfPermission(this,
                   permission.ACCESS_BACKGROUND_LOCATION)
                   == PackageManager.PERMISSION_GRANTED;

       if (backgroundLocationPermissionApproved) {
           // App可以访问前台和后台定位权限
           // 启动后台Service或者带“location”的前台Service
       } else {
           // App只能使用前台定位,显示一个Dialog提醒用户,你的App需要后台定位权限。
           // 然后申请后台定位权限
           ActivityCompat.requestPermissions(this, new String[] {
               Manifest.permission.ACCESS_BACKGROUND_LOCATION},
               your-permission-request-code);
       }
    } else {
       // App没有任何定位权限,重新申请全部定位相关权限
       ActivityCompat.requestPermissions(this, new String[] {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_BACKGROUND_LOCATION
            },
            your-permission-request-code);
    }

后记

原本是准备做一套比较全的代码发上来,可以自动根据权限,开启对应服务这么一套代码,包括AndroidQ的权限申请和Service启动逻辑。但是后来由于没有真实的设备来给我测试,我不敢说我写的东西一定工作正常,所以目前暂时决定这个系列不加入我个人封装的AndroidQ相关的代码,以后再说。第三期大概率讲一讲android.permission.READ_PHONE_STATE,相关的改动,毕竟这个比较容易一些,这期就到这里。

如果看不懂或者我写的有问题的地方,欢迎在评论中指出,大家一切探究讨论!

    原文作者:飞吧小蚊子
    原文地址: https://www.jianshu.com/p/dab9c3179d99
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞