赞
踩
Android 6.0之后,蓝牙扫描回调需要获取模糊定位查询,Android 10之后更严格,需要获取精确定位。
这些年Google对安卓的控制可谓是越来越严谨了,安全性也是越来越高。
现在的问题是,当你的targetSDK>22的时候,扫描蓝牙就不不会有回调了,而且即使是在Manifest中添加了permission也依然无法获取回调,解决办法如下:
android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { applicationId "com.hicling.iictcling" minSdkVersion 18 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { // 设置支持的SO库架构,第三方给的so库哪几种架构,就配置这几种架构 abiFilters 'armeabi' , 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' } } .......
以上办法比较愚蠢,会导致app的目标sdk过老旧,手机可能会提示兼容性问题,很不靠谱,建议仅仅是要解决问题的偷懒可以这个干,真要解决这个蓝牙回调权限问题请参照法二,如下:
第一部,修改Manifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.hicling.iictcling"> <!--关键代码--> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /> <application android:name=".App" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:targetApi="q">
第二部,手动开启权限的kotlin代码(注意android10开始,这个蓝牙permission通过manifest已经无法激活成功了,需要手动向用户提示,让用户打开哦。
/** * 解决:无法发现蓝牙设备的问题 */ private val accessCode = 101 private val permissions: Array<String> = arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) private var countRequest = 0 // get bluetooth permission private fun getBlePermission() { countRequest++ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { var permissionCheck = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) permissionCheck += checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) if (permissionCheck != PackageManager.PERMISSION_GRANTED) { requestPermissions(permissions, accessCode) } } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { accessCode -> if (checkPermission(grantResults)) { Log.i(tag, "onRequestPermissionsResult: 用户允许权限 accessCode:$accessCode") } else { Log.i(tag, "onRequestPermissionsResult: 拒绝搜索设备权限 accessCode:$accessCode") if (countRequest > 2) { // ask User to grant permission manually AlertDialog.Builder(this) .setMessage(R.string.open_permission_req) .setTitle(R.string.request) .setPositiveButton(R.string.confirm) { _, _ -> goIntentSetting() }.create().show() } else getBlePermission() } } } private fun checkPermission(grantResults: IntArray): Boolean { for (grantResult in grantResults) { if (grantResult == PackageManager.PERMISSION_DENIED) { return false } } return true } // open app settings let user grant the permission private fun goIntentSetting() { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri: Uri = Uri.fromParts("package", this.packageName, null) intent.data = uri try { this.startActivity(intent) } catch (e: Exception) { e.printStackTrace() } }
注意上面有个打开app设置的方法,因为如果用户两次拒绝permission的话,app将不再弹出获取permission的提示,需要用户从setting中打开,故而在上述代码逻辑中判断用户是否已经被两次拒绝,如果是将会打开setting设置,催促用户手动打开权限。
以下是扫描蓝牙设备的样例代码,仅供参考。
mWebView.registerHandler("scanBle", WVJBWebView.WVJBHandler<Any?, Any?> { data, function -> Log.i(tag, "js call scanBle") Log.i(tag, data.toString()) val data = Gson().fromJson(data.toString(), TimeData::class.java) if (checkBle()) { val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult?) { super.onScanResult(callbackType, result) val msg = "BleScan results" Log.i(tag, msg) Log.i(tag, result.toString()) function.onResult(json(1, result, msg)) } override fun onBatchScanResults(results: MutableList<ScanResult>?) { super.onBatchScanResults(results) val msg = "Batch Scan Results" Log.i(tag, msg) Log.i(tag, results.toString()) function.onResult(json(1, results, msg)) } override fun onScanFailed(errorCode: Int) { super.onScanFailed(errorCode) val msg = "BleScan fail to scan errorCode: $errorCode" Log.i(tag, msg) Log.i(tag, errorCode.toString()) function.onResult(json(0, null, msg)) } } val scanner = BluetoothAdapter.getDefaultAdapter().bluetoothLeScanner Log.i(tag, "start scan for ${data.time / 1000}s") scanner.startScan(scanCallback) handler.postDelayed({ scanner.stopScan(scanCallback) Log.i(tag, "stop scan ble") }, data.time) } })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。