zoukankan      html  css  js  c++  java
  • Android踩坑之解决蓝牙无法回调问题-Kotlin示例

    Android 6.0之后,蓝牙扫描回调需要获取模糊定位查询,Android 10之后更严格,需要获取精确定位。

    这些年Google对安卓的控制可谓是越来越严谨了,安全性也是越来越高。

    现在的问题是,当你的targetSDK>22的时候,扫描蓝牙就不不会有回调了,而且即使是在Manifest中添加了permission也依然无法获取回调,解决办法如下:

    TargetSdk降级到22——降级法

    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设置,催促用户手动打开权限。

    Example

    以下是扫描蓝牙设备的样例代码,仅供参考。

    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)
                }
            })
    
  • 相关阅读:
    危机边缘第五季/全集Fringe迅雷下载
    危机边缘第一季/全集Fringe迅雷下载
    混乱之子第七季/全集Sons of Anarchy迅雷下载
    混乱之子第一季/全集Sons Of Anarchy迅雷下载
    都市侠盗第五季/全集Leverage迅雷下载
    都市侠盗第一季/全集Leverage迅雷下载
    识骨寻踪第十二季/全集Bones迅雷下载
    识骨寻踪第一季/全集Bones迅雷下载
    神盾局特工第四季/全集Agents Of SHIELD迅雷下载
    福尔摩斯基本演绎法第一季/全集Elementary迅雷下载
  • 原文地址:https://www.cnblogs.com/devilyouwei/p/13094851.html
Copyright © 2011-2022 走看看