公告

公告:6月1日起论坛仅作为产品公告及开发者交流平台,如您的问题需百度工程师解答请前往 「反馈平台」 咨询,3个工作日内专人回复。

查看: 38661|回复: 17

[资源分享] Android 6.0 及以上系统定位开发权限注意事项

[复制链接]
senny_hi 发表于 2016-8-18 14:02:35 | 显示全部楼层 |阅读模式
本帖最后由 senny_hi 于 2016-8-18 14:04 编辑

近期发现很多开发者反馈定位开发过程中遇到返回错误码 167 的情况。
原因是:
Google在Android 6.0中引入了动态权限获取机制(Runtime Permission),使得Android的权限管理更加严格完善。
动态权限获取要求开发者在调用涉及相关权限的代码时,使用系统接口来动态得申请相应权限。我们定位SDK涉及权限即在此范畴中。
在未获取到定位权限情况下,定位SDK获取到的定位依据(基站,Wifi)均为空值,因此无法有效定位,定位服务会返回167结果。

动态权限机制的开启:
6.0对于动态权限机制的开启主要根据应用设定的targetSdkVersion,具体来讲:
  
targetSdkVersion
  
是否默认禁用敏感权限
是否开启动态权限
<23
>=23

因此需要在项目配置文件中修改您的targetSdkVersion配置。
对于Eclipse环境,请更改AndroidManifest.xml中代码;
AndroidStudio环境,请更改build.gradle中的代码。

动态权限代码样例:
在Android 6.0系统中,需要动态获取的权限涉及到:
//获取手机状态:
Manifest.permission.READ_PHONE_STATE
//获取位置信息:
Manifest.permission.ACCESS_COARSE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
//读写SD卡:
Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE

获取权限使用API:
int android.content.Context.checkSelfPermission(String permission)
此接口会触发系统弹窗,用户选择后触发Activity中的回调函数:
void YourActivity.onRequestPermissionsResult(intrequestCode, String[] permissions, int[] grantResults)
无标题.png

以READ_PHONE_STATE为例:
private static final int BAIDU_READ_PHONE_STATE =100;    //自定义一个权限获取码,用于回调函数中做对应处理

调用checkSelfPermission接口申请权限:
if(mContext.checkSelfPermission(Manifest.permission.READ_PHONE_STATE) !=PackageManager.PERMISSION_GRANTED) {
    // 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)
   requestPermissions( new String[] { Manifest.permission.READ_PHONE_STATE}, BAIDU_READ_PHONE_STATE);
}

在Activity的onRequestPermissionResult回调函数中做处理:
@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
   super.onRequestPermissionsResult(requestCode, permissions,grantResults);
switch(requestCode) {
    // requestCode即所声明的权限获取码,在checkSelfPermission时传入
        caseBAIDU_READ_PHONE_STATE:
           if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 获取到权限,作相应处理(调用定位SDK应当确保相关权限均被授权,否则可能引起定位失败)
            } else{
                // 没有获取到权限,做特殊处理
            }
            break;
        default:
            break;
     }
}

Android 6.0系统的位置开关:
我的手机是6.0系统,定位误差非常大,是怎么回事?
Android 6.0原生系统与部分厂商定制的6.0系统在系统定位开关表现上稍有差异。具体来讲:
  
系统
  
开关名称
对定位的影响
  
原生系统(也包括未进行定制的系统)
  
位置信息
原生系统下,位置开关控制影响到系统级的GPS及网络定位:
  
在关闭位置开关情况下,应用无法获取到Wifi信息,也无法使用GPS,仅可使用基站定位(cl类型)*,造成定位误差变大;
  
打开位置开关后,应用可以使用Wifi信息或GPS进行定位,会大幅提升定位精度
  
第三方、厂商定制系统
  
GPS
厂商定制系统(部分)开关仅影响GPS使用:
  
关闭GPS开关情况下,应用仍可访问到Wifi信息,可以使用wifi定位
  
打开GPS开关情况下,应用才可以使用GPS定位
*注:
1.关于原生系统定位开关会影响Wifi获取的问题,可参照Google Android Bug反馈论坛:
这是6.0原生系统已知问题,需要Google修复;厂商定制ROM表现会有所差异
也可参照国内一些开发者文章描述:

2.部分早期6.0版存在位置开关关闭后无法定位的问题,目前测试最新的6.0版本原生系统,已不存在此问题。
针对6.0系统的位置开关问题。由于GPS设置的行为在各版本中一致,因此可以简单的使用系统API来判断用户是否打开了位置按钮,
让检测到系统版本为6.0,并且用户未打开按钮时,进行提示。
LocationManagerlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if(!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    // 未打开位置开关,可能导致定位失败或定位不准,提示用户或做相应处理
}

ALWAYS_COOL 发表于 2017-4-28 15:38:29 | 显示全部楼层
执行了checkPermission 并且权限都获得 还是167,谁能给解答一下
回复 支持 1 反对 1

使用道具 举报

殇满楼城 发表于 2016-8-22 14:09:18 | 显示全部楼层
估计6.0定位失败就是这个原因!
回复 支持 1 反对 0

使用道具 举报

爱跑的乖乖狼 发表于 2016-8-18 14:43:22 | 显示全部楼层
本帖最后由 爱跑的乖乖狼 于 2016-8-18 14:44 编辑

终于见到一个正经的版主了,赞一个,正是我需要的
求学呮路 发表于 2016-9-19 09:12:17 | 显示全部楼层
为什么我的6.0只要一进定位 APP 就直接崩了 也是这个原因吗?
lovelyelfpop 发表于 2016-9-22 09:09:06 | 显示全部楼层
求学呮路 发表于 2016-9-19 09:12
为什么我的6.0只要一进定位 APP 就直接崩了 也是这个原因吗?

我的android 6.0 原生 也定位不了。官方demo都不能,用的是最新的 Android 定位SDK v7.0 (全球定位版)
求学呮路 发表于 2016-9-22 09:11:06 | 显示全部楼层
lovelyelfpop 发表于 2016-9-22 09:09
我的android 6.0 原生 也定位不了。官方demo都不能,用的是最新的 Android 定位SDK v7.0 (全球定位版) ...

用了7.0的 可以了吗?
lovelyelfpop 发表于 2016-9-22 09:15:30 | 显示全部楼层
求学呮路 发表于 2016-9-22 09:11
用了7.0的 可以了吗?

就是用了最新的 定位sdk7.0,无法定位啊。
旧的   定位sdk 6.3a 版本都能定位
williamwue 发表于 2016-10-18 11:20:13 | 显示全部楼层
正好在尝试寻找android 6.0 定位相关问题的解决办法,版主解释的很详细,赞一个
c786909486 发表于 2016-11-19 20:17:13 | 显示全部楼层
版主,这个7.0的有问题啊,安卓6.0的弄了一晚上都定位不了,换成6.13的立马就好了
用户_5pahvn3wc 发表于 2016-12-5 21:09:08 | 显示全部楼层
怎么修改呀?我是新手不太知道,要        //获取手机状态:
        Manifest.permission.READ_PHONE_STATE
        //获取位置信息:
        Manifest.permission.ACCESS_COARSE_LOCATION
        Manifest.permission.ACCESS_FINE_LOCATION
        //读写SD卡:
        Manifest.permission.READ_EXTERNAL_STORAGE
        Manifest.permission.WRITE_EXTERNAL_STORAGE
这些塞到哪里呢
用户_5pahvn3wc 发表于 2016-12-5 21:09:38 | 显示全部楼层
c786909486 发表于 2016-11-19 20:17
版主,这个7.0的有问题啊,安卓6.0的弄了一晚上都定位不了,换成6.13的立马就好了 ...

您好,这个怎么修改呀?
        Manifest.permission.READ_PHONE_STATE
        //获取位置信息:
        Manifest.permission.ACCESS_COARSE_LOCATION
        Manifest.permission.ACCESS_FINE_LOCATION
        //读写SD卡:
        Manifest.permission.READ_EXTERNAL_STORAGE
        Manifest.permission.WRITE_EXTERNAL_STORAGE
这些塞到哪里呢
fallingstar16 发表于 2017-2-11 16:09:22 | 显示全部楼层
方法尝试了,在华为安卓7.0是可以定位成功的,是华为安卓6.0即使动态打开权限后依然无法定位成功,不知道是什么原因。
___蓝调o 发表于 2017-2-28 11:03:33 | 显示全部楼层
java.lang.IllegalArgumentException: You cannot keep your settings in the secure settings.
得到权限后出现这个错误怎么办?
求知小猫猫 发表于 2017-5-8 16:46:19 | 显示全部楼层
用户_5pahvn3wc 发表于 2016-12-5 21:09
怎么修改呀?我是新手不太知道,要        //获取手机状态:
        Manifest.permission.READ_PHONE_STAT ...

http://lbsyun.baidu.com/index.php?title=androidsdk/guide/location
申请一个android密钥 跟着做
crst_绝对零度 发表于 2017-5-12 14:39:13 | 显示全部楼层
fallingstar16 发表于 2017-2-11 16:09
方法尝试了,在华为安卓7.0是可以定位成功的,是华为安卓6.0即使动态打开权限后依然无法定位成功,不知道是 ...

我也是一样的问题,再华为6.0上,即使弹框打开定位权限,仍然报167,层主有解决方法了么?
crst_绝对零度 发表于 2017-5-12 14:56:17 | 显示全部楼层
crst_绝对零度 发表于 2017-5-12 14:39
我也是一样的问题,再华为6.0上,即使弹框打开定位权限,仍然报167,层主有解决方法了么? ...

楼主上面说过,早期的6.0版本,如果没有打开gps也是不能定位成功的,我这边一台荣耀畅玩5C应该就是此问题导致的。除了提示用户打开gps以为,没有其他办法了。
小爽丶还是可以 发表于 2017-8-28 22:49:17 | 显示全部楼层
ALWAYS_COOL 发表于 2017-4-28 15:38
执行了checkPermission 并且权限都获得 还是167,谁能给解答一下

同求....................贼踏马烦

小黑屋|手机版|百度地图开放平台 ( 京ICP证030173号 )

GMT+8, 2018-12-17 04:02 , Processed in 0.203795 second(s), 23 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表