🐉0、简介
- 更新填补上一章的漏洞(😎:咱有始有终。)
- 雇佣哥俩好:大哥是 Handler 掌舵人,(😃:瞧这名字开真威风!久仰久仰。)二哥是 Thread 线人。(😑:那里来的二五仔?)
- 联络蓝牙大哥,因为还没有开灯嘛!(蓝牙🦄:叽里咕噜…😅:尽是黑话,跑龙套的初哥那去了?没办法,我来翻译翻译。)
🐰1、更新:密码无人输入的漏洞
有的朋友可能会发现,在发现蓝牙后,新蓝牙机要输入密码。但是无人输入密码的话,30 至 40 秒之间,页面就会自动关闭。这个 App 还会停留在 Bonding 阶段。
BleHc05Observer:
ACTION_BOND_STATE_CHANGED -> {
lgd(tag + "Checking Bonded State...")
val device: BluetoothDevice =
intent.getParcelableExtra<Parcelable>(
EXTRA_DEVICE
) as BluetoothDevice
when (device.bondState) {
BOND_BONDED -> {
lgd("$tag Bonded to device")
devStatus.postValue(BONDED)
}
BOND_BONDING -> {
lgd("$tag Bonding to device")
// 什么都没有,卡!
}
BOND_NONE -> {
lge("$tag Nothing has bonded.")
devStatus.postValue(FAIL)
}
}
}
结果:

🙄:在 bonding 加料。
BOND_BONDING -> {
lgd("$tag Bonding to device")
devStatus.postValue(BONDING)
}
设定是新机就加个时限,没人输入密码就跳到 FAIL。我还加了显示倒数功能。

MainActivity:瞧瞧,咱这个MVVM 好啊!现在指令一目了然,逻辑的事 ViewModel 都帮我干了。😭老子在 MVC 的那里可是乱啊,又当爹又当妈的、、、
//region vars:
...
private val counterTV: TextView by
lazy { findViewById(R.id.counterTV) }
...
private var newDevice = false
private var counter = 0
private var bonded = false
//endregion
...
》》》在 **onCreate()** 里面:
mainVM.deviceStatus.observe(
this,
{ status ->
when (status) {
...
PAIRING -> {
val info = "Searching Bonded List..."
infoTV.text = info
progressBar.visibility = View.VISIBLE
mainVM.checkBondedList()
}
DISCOVERING -> {
val info = "Discovering device in range..."
infoTV.text = info
progressBar.visibility = View.VISIBLE
newDevice = true
mainVM.discovering()
}
BONDING -> {
val info = "Device Found in Record!\nBonding..."
infoTV.text = info
if (newDevice)
mainVM.checkNewDevice()
else
mainVM.bonding()
}
DISCOVERED -> {
val pass = "Your Pass: ${ConfigHelper.getPass()}"
discoveryTV.text = pass
discoveryTV.visibility = View.VISIBLE
}
BONDED -> {
lgd("MainAct: Bonded successful!")
counterTV.visibility = View.GONE
counter = 0
bonded = true
discoveryTV.text = ""
discoveryTV.visibility = View.GONE
progressBar.visibility = View.GONE
val info = "Bonded to $DEVICE_NAME."
infoTV.text = info
msg(this, info, 1)
mainVM.connected()
}
CONNECTED -> {
val info = "Device connected..."
infoTV.text = info
onBT.visibility = View.VISIBLE
progressBar.visibility = View.GONE
}
FAIL -> {
counter = 0
counterTV.visibility = View.GONE
val info = "FAIL to create connection!" +
"\nOr\nPassword is incorrect!"
infoTV.text = info
discoveryTV.visibility = View.GONE
progressBar.visibility = View.GONE
tryAgainBT.visibility = View.VISIBLE
}
NOT_FOUND -> {
lgd("MainAct: Device Not Found.")
progressBar.visibility = View.GONE
val info = "Device NOT Found!"
infoTV.setTextColor(Color.RED)
infoTV.text = info
msg(this, info, 1)
}
COUNT_DOWN -> {
if (!bonded) {
counterTV.visibility = View.VISIBLE
val down = 35 - counter
counter++
val timer = "35s to Enter Password: $down"
counterTV.text = timer
}
}
...
➕ COUNT_DOWN 进 DeviceStatus:
enum class DeviceStatus {
PAIRING, BONDING, DISCOVERING, SWITCHING,
DISCOVERED, BONDED, CONNECTED,
FAIL, DISCONNECT, NOT_FOUND, COUNT_DOWN
}
那个 MainViewModel 当然要改啦:
fun bonding() {
val result = bleHelper.checkDeviceBonding()
lgd("$tag Bonding...$result")
if (result) {
deviceStatus.postValue(CONNECTED)
//bleHelper.discoverService()
} else {
deviceStatus.postValue(FAIL)
}
}
...
fun checkNewDevice() {
// new password entry timeout is 40s
viewModelScope.launch {
repeat(40) {
deviceStatus.postValue(COUNT_DOWN)
delay(SEC)
}
if (!bleHelper.checkBondedList()) {
lgd("Check Bonded List.")
deviceStatus.postValue(FAIL)
}
}
}
这里 SEC = 1000L;方程用的是 Coroutines,异步程序。我设定 40秒 内去 COUNT_DOWN 跳数字;40 秒后,蓝牙没有上榜的话就跳去 FAIL。写完,Ctrl+K,上传。开始测。

不错不错,能够显示 FAIL 部分。

本文介绍了使用Androidx通过Handler和Thread处理蓝牙HC05的连接,修复了密码输入漏洞,详细阐述了蓝牙的捆绑、连接、点灯操作,并探讨了异步点灯方法及UUID开关的实验,最终实现稳定的蓝牙控制。
最低0.47元/天 解锁文章
5004

被折叠的 条评论
为什么被折叠?



