Android Things运行BLE室内定位Demo时出现位置服务禁用错误
解决Android Things上BLE扫描提示“Location Services disabled (code 4)”的问题
我之前在Android Things设备上也碰到过类似的BLE扫描问题,结合你的场景给你几个可行的解决方案:
先理清楚你的问题
你在NXP i.MX7D开发套件的Android Things系统上运行BLE室内定位Demo时,触发了这个错误:
Bluetooth scanning error: Location Services disabled (code 4)
对应的完整堆栈信息如下:
E/BluetoothClient: Bluetooth scanning error: Location Services disabled (code 4) W/System.err: com.polidea.rxandroidble.exceptions.BleScanException: Location Services disabled (code 4) W/System.err: at com.polidea.rxandroidble.internal.scan.ScanPreconditionsVerifierApi18.verify(ScanPreconditionsVerifierApi18.java:31) W/System.err: at com.polidea.rxandroidble.internal.scan.ScanPreconditionsVerifierApi24.verify(ScanPreconditionsVerifierApi24.java:38) W/System.err: at com.polidea.rxandroidble.RxBleClientImpl$1.call(RxBleClientImpl.java:114) W/System.err: at com.polidea.rxandroidble.RxBleClientImpl$1.call(RxBleClientImpl.java:111) W/System.err: at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) W/System.err: at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) W/System.err: at rx.Observable.subscribe(Observable.java:10352) W/System.err: at rx.Observable.subscribe(Observable.java:10319) W/System.err: at rx.Observable.subscribe(Observable.java:10227) W/System.err: at com.nexenio.bleindoorpositioningdemo.bluetooth.BluetoothClient.startScanning(BluetoothClient.java:79) W/System.err: at com.nexenio.bleindoorpositioningdemo.HomeActivity.onResume(HomeActivity.java:108) W/System.err: at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1355) W/System.err: at android.app.Activity.performResume(Activity.java:7118) W/System.err: at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556) W/System.err: at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621) W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862) W/System.err: at android.app.ActivityThread.-wrap11(Unknown Source:0) W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106) W/System.err: at android.os.Looper.loop(Looper.java:164) W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6494) W/System.err: at java.lang.reflect.Method.invoke(Native Method) W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
你的应用用RxAndroidBle处理蓝牙逻辑,也已经在清单里声明了必要权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
确实,Android Things会自动授予这些危险权限,但位置服务默认是关闭的,而且它没有普通Android的设置界面,得用特殊方法开启。
具体解决方案
1. 最快的方式:用ADB命令手动开启
这是最直接的方法,连接上你的开发套件,在电脑终端执行这条命令:
adb shell settings put secure location_providers_allowed +gps,network
这条命令会同时启用GPS和网络定位服务,满足BLE扫描对位置服务的要求。如果之后需要关闭,把+换成-就行:
adb shell settings put secure location_providers_allowed -gps,network
2. 代码里做检查和提示
Android Things不允许应用直接修改系统设置,所以你只能在代码里先检查位置服务是否开启,如果没开就给用户提示:
// 获取LocationManager实例 LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); // 检查GPS或网络定位是否启用 boolean isLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); if (!isLocationEnabled) { // 显示提示,告诉用户需要通过ADB命令开启位置服务 Toast.makeText(this, "请通过ADB命令开启位置服务:adb shell settings put secure location_providers_allowed +gps,network", Toast.LENGTH_LONG).show(); }
另外,虽然Android Things会自动授权,但保险起见可以加个权限检查:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Log.w("BLEDemo", "位置权限未授予,可能影响扫描功能"); }
3. 理解Android Things的限制
Android Things是针对嵌入式设备设计的,做了很多精简,位置服务默认关闭,而且没有用户交互的设置界面,这类系统级的配置只能通过ADB或者设备的系统配置文件来修改,应用本身没有权限去调整,这一点和普通Android手机不一样,得注意。
内容的提问来源于stack exchange,提问作者Steppschuh




