Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析

发布时间:2017-6-29 9:53:39编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析",主要涉及到Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析方面的内容,对于Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析感兴趣的同学可以参考一下。

http://blog.csdn.net/zrf1335348191/article/details/53487222

问题描述:

转载请注明出处,from 

fang_fang_story



近期做一个扫描附近低功耗蓝牙设备获取到rssi并进行一系列的相对的定位的功能。在开发前期一直使用低版本(Android6.0以下)的手机进行测试,没有任何问题。在运行到Android6.0的手机上后,出了一个问题。

每当扫描到附近ble设备并进行回调时都会报错,根本获取不了扫描的结果,报错如下:

[java] view plain copy
  1. D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5  
  2. W/Binder: Caught a RuntimeException from the binder stub implementation.  
  3.    java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get   
  4. scan results  
  5.          at android.os.Parcel.readException(Parcel.java:1620)  
  6.          at android.os.Parcel.readException(Parcel.java:1573)  
  7.          at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)  
  8.          at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:324)  
  9.          at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)  
  10.          at android.os.Binder.execTransact(Binder.java:453)  

问题分析解决:

从log中可以看到一个解决方案,那就是Need ......permission to get scan results : 获取扫描结果需要位置权限,

i>,接下来就是往Androidmanifest.xml配置文件中添加权限

[java] view plain copy
  1. <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
  2.    <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>  

但是就算是添加了权限,在获取扫描结果时依旧会提示Need...permission...的问题,这是为什么呢?因为Android6.0中的一些权限需要在代码中动态申请


ii>,于是需要在代码中动态申请所需要的权限

[java] view plain copy
  1. //Android6.0需要动态申请权限  
  2.                if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)  
  3.                        != PackageManager.PERMISSION_GRANTED) {  
  4.                    //请求权限  
  5.                    ActivityCompat.requestPermissions(this,  
  6.                            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,  
  7.                                    Manifest.permission.ACCESS_FINE_LOCATION},  
  8.                            IntentCons.REQUEST_LOCATION_PERMISSION);  
  9.                    if (ActivityCompat.shouldShowRequestPermissionRationale(this,  
  10.                            Manifest.permission.ACCESS_COARSE_LOCATION)) {  
  11.                        //判断是否跟用户做一个说明  
  12.                        DialogUtils.shortT(getApplicationContext(), "需要蓝牙权限");  
  13.                    }  
  14.                }  


运行一下,果然应用会询问权限是否允许,效果如图



是不是觉得程序没有问题了?博主也是这么认为滴惊讶,允许权限之后发现,虽然不再报异常,但依旧刷新不出来结果(如果你的位置信息功能是开启的则就另说了,具体原因看第三条分析)

iii>,你目前只是有了使用设备的位置信息的权限,但是你还没有打开位置信息,所以就算有了权限也没办法使用。你可以验证一下----

验证不需要在代码中验证,你在做完第二步并且同意了访问位置信息的权限后,打开手机的位置信息功能。

打开方式一:进入设置打开位置信息

打开方式二:手机下拉导航栏的快捷设置中快捷设置



打开之后是不是发现应用可以获取扫描结果了呢?哈哈,博主已测过,没有问题。


解决方案:

综上分析,可以确定完美解决方案:

要想获取扫描结果,一是保证位置信息已经打开,二是保证应用已经动态申请了所需要的权限

第一步,保证位置信息打开:

[java] view plain copy
  1. /** 
  2.     *判断位置信息是否开启 
  3.     * @param context 
  4.     * @return 
  5.     */  
  6.    public static boolean isLocationOpen(final Context context){  
  7.        LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);  
  8.        //gps定位  
  9.        boolean isGpsProvider = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);  
  10.        //网络定位  
  11.        boolean isNetWorkProvider = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);  
  12.        return isGpsProvider|| isNetWorkProvider;  
  13.    }  
首先是判断位置信息是否开启,若未开启则开启:

[java] view plain copy
  1. //开启位置服务,支持获取ble蓝牙扫描结果  
  2.         if (Build.VERSION.SDK_INT >= 23 && !NetUtils.isLocationOpen(getApplicationContext())) {  
  3.             Intent enableLocate = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);  
  4.             startActivityForResult(enableLocate, IntentCons.REQUEST_LOCATION_PERMISSION);  
  5.         }  
在这里判断了一下Android版本,因为只有6.0以上才需要这么做。

并且在该activity中重写onActivityResult方法,在位置开启成功后去申请权限,当然除了在代码中申请在清单配置文件中也是需要写的,如果未开启位置信息则进行其他处理

[java] view plain copy
  1. @Override  
  2.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         if (requestCode == IntentCons.REQUEST_LOCATION_PERMISSION) {  
  4.             if (NetUtils.isLocationOpen(getApplicationContext())) {  
  5.                 Log.i("fang"" request location permission success");  
  6.                 //Android6.0需要动态申请权限  
  7.                 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)  
  8.                         != PackageManager.PERMISSION_GRANTED) {  
  9.                     //请求权限  
  10.                     ActivityCompat.requestPermissions(this,  
  11.                             new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,  
  12.                                     Manifest.permission.ACCESS_FINE_LOCATION},  
  13.                             IntentCons.REQUEST_LOCATION_PERMISSION);  
  14.                     if (ActivityCompat.shouldShowRequestPermissionRationale(this,  
  15.                             Manifest.permission.ACCESS_COARSE_LOCATION)) {  
  16.                         //判断是否需要解释  
  17.                         DialogUtils.shortT(getApplicationContext(), "需要蓝牙权限");  
  18.                     }  
  19.                 }  
  20.   
  21.             } else {  
  22.                 //若未开启位置信息功能,则退出该应用  
  23.                 finish();  
  24.             }  
  25.         }  
  26.   
  27.         super.onActivityResult(requestCode, resultCode, data);  
  28.   
  29.     }  

效果如下




哈哈,perfect,问题完美解决,有用的话留个爪儿吧偷笑





7
0



上一篇:通达OA二次开发 小飞鱼应用OA工作流二次开发智能公文系统(三)(图文)
下一篇:高性能Mysql笔记 (4) -

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款