如何解决Kotlin 的协程如何帮助我们处理低功耗蓝牙
我在主要活动(导航组件)中使用低功耗蓝牙。
Ble:每 10 秒对 BEACON 附近的目标进行扫描。
问题是扫描和连接信标应用程序的性能很慢。
希望协程能解决这个问题,Kotlin 的协程如何帮助我们处理 BLE 扫描和回调?
import android.annotation.TargetApi
import android.bluetooth.*
import android.bluetooth.BluetoothAdapter.LeScanCallback
import android.bluetooth.le.*
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.util.*
@TargetApi(21)
class MainActivityScan : AppCompatActivity() {
private var mBluetoothAdapter: BluetoothAdapter? = null
private val REQUEST_ENABLE_BT = 1
private var mHandler: Handler? = null
private var mLEScanner: BluetoothLeScanner? = null
private var settings: ScanSettings? = null
private var filters: List<ScanFilter>? = null
private var mGatt: BluetoothGatt? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mHandler = Handler()
if (!packageManager.hasSystemFeature(PackageManager.FEATURE_BLUetoOTH_LE)) {
Toast.makeText(this,"BLE Not Supported",Toast.LENGTH_SHORT).show()
finish()
}
val bluetoothManager = getSystemService(BLUetoOTH_SERVICE) as BluetoothManager
mBluetoothAdapter = bluetoothManager.adapter
}
override fun onResume() {
super.onResume()
if (mBluetoothAdapter == null || !mBluetoothAdapter!!.isEnabled) {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT)
} else {
if (Build.VERSION.SDK_INT >= 21) {
mLEScanner = mBluetoothAdapter!!.bluetoothLeScanner
settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build()
filters = ArrayList()
}
scanLeDevice(true)
}
}
override fun onPause() {
super.onPause()
if (mBluetoothAdapter != null && mBluetoothAdapter!!.isEnabled) {
scanLeDevice(false)
}
}
override fun onDestroy() {
if (mGatt == null) {
return
}
mGatt!!.close()
mGatt = null
super.onDestroy()
}
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_CANCELED) {
//Bluetooth not enabled.
finish()
return
}
}
super.onActivityResult(requestCode,resultCode,data)
}
private fun scanLeDevice(enable: Boolean) {
if (enable) {
mHandler!!.postDelayed({
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter!!.stopLeScan(mLeScanCallback)
} else {
mLEScanner!!.stopScan(mScanCallback)
}
},SCAN_PERIOD)
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter!!.startLeScan(mLeScanCallback)
} else {
mLEScanner!!.startScan(filters,settings,mScanCallback)
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter!!.stopLeScan(mLeScanCallback)
} else {
mLEScanner!!.stopScan(mScanCallback)
}
}
}
private val mScanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int,result: ScanResult) {
Log.i("callbackType",callbackType.toString())
Log.i("result",result.toString())
val btDevice = result.device
connectToDevice(btDevice)
}
override fun onBatchScanResults(results: List<ScanResult>) {
for (sr in results) {
Log.i("ScanResult - Results",sr.toString())
}
}
override fun onScanFailed(errorCode: Int) {
Log.e("Scan Failed","Error Code: $errorCode")
}
}
private val mLeScanCallback = LeScanCallback { device,RSSi,scanRecord ->
runOnUiThread {
Log.i("onLeScan",device.toString())
connectToDevice(device)
}
}
fun connectToDevice(device: BluetoothDevice) {
if (mGatt == null) {
mGatt = device.connectGatt(this,false,gattCallback)
scanLeDevice(false) // will stop after first device detection
}
}
private val gattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt,status: Int,newState: Int) {
Log.i("onConnectionStateChange","Status: $status")
when (newState) {
BluetoothProfile.STATE_CONNECTED -> {
Log.i("gattCallback","STATE_CONNECTED")
gatt.discoverServices()
}
BluetoothProfile.STATE_disCONNECTED -> Log.e("gattCallback","STATE_disCONNECTED")
else -> Log.e("gattCallback","STATE_OTHER")
}
}
override fun onServicesdiscovered(gatt: BluetoothGatt,status: Int) {
val services = gatt.services
Log.i("onServicesdiscovered",services.toString())
gatt.readCharacteristic(services[1].characteristics[0])
}
override fun onCharacteristicRead(gatt: BluetoothGatt,characteristic: BluetoothGattCharacteristic,status: Int) {
Log.i("onCharacteristicRead",characteristic.toString())
gatt.disconnect()
}
}
companion object {
private const val SCAN_PERIOD: Long = 10000
}
}
解决方法
您应该尝试将扫描部分移至 IO
线程,这可能有助于提高性能。还有这个库:https://github.com/NordicSemiconductor/Android-BLE-Library 是 BLE 应用的绝佳选择
如果您打算为此使用协程,您可以使用流对扫描逻辑进行建模,即 flowOn(Dispatchers.IO)
,并使用来自 Kotlin 的 Flow
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。