您当前的位置: Android SDK > 开发指南 > Android 6.0系统开发须知
Android 6.0系统开发须知

开启动态权限机制的原因

Google在Android 6.0中引入了动态权限获取机制(Runtime Permission),使得Android的权限管理更加严格完善。

动态权限获取要求开发者在调用涉及相关权限的代码时,使用系统接口来动态得申请相应权限。定位SDK涉及权限即在此范畴中。

在未获取到定位权限情况下,定位SDK获取到的定位依据(基站、WiFi)均为空值,因此无法有效定位,定位服务会返回错误码167。

动态权限机制的开启

Android 6.0对于动态权限机制的开启主要根据应用设定的targetSdkVersion,具体来讲:

targetSdkVersion 是否默认禁用敏感权限 是否开启动态权限
<23
>=23

因此需要在项目配置文件中修改您的targetSdkVersion配置。

对于Eclipse环境,请更改AndroidManifest.xml中代码;AndroidStudio环境,请更改build.gradle中的代码。

动态权限代码样例

在Android 6.0系统中,需要动态获取的权限涉及到:

1、获取手机状态:

Manifest.permission.READ_PHONE_STATE


2、获取位置信息:

Manifest.permission.ACCESS_COARSE_LOCATION

Manifest.permission.ACCESS_FINE_LOCATION


3、读写SD卡:

Manifest.permission.READ_EXTERNAL_STORAGE

Manifest.permission.WRITE_EXTERNAL_STORAGE

获取权限使用API

1、int android.content.Context.checkSelfPermission(String permission),此接口会触发系统弹窗,用户选择后触发Activity中的回调函数:

void YourActivity.onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

Android6.0_20160822.png

以READ_PHONE_STATE为例:

private static final int BAIDU_READ_PHONE_STATE =100;

2、自定义一个权限获取码,用于回调函数中做对应处理 调用checkSelfPermission接口申请权限:

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

3、在Activity的onRequestPermissionResult回调函数中做处理:

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

Android 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反馈论坛:

https://code.google.com/p/android/issues/detail?id=185370

这是Android6.0原生系统已知问题,需要Google修复;

厂商定制ROM表现会有所差异。也可参照国内一些开发者文章描述:

http://www.jianshu.com/p/3400ca0deeee.


2.部分早期Android6.0版存在位置开关关闭后无法定位的问题,目前测试最新的Android6.0版本原生系统,已不存在此问题。

针对6.0系统的位置开关问题。由于GPS设置的行为在各版本中一致,因此可以简单的使用系统API来判断用户是否打开了位置按钮,让检测到系统版本为6.0,并且用户未打开按钮时,进行提示。

LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
 
if(!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
 
    // 未打开位置开关,可能导致定位失败或定位不准,提示用户或做相应处理
}