[英]Unable to Connect to BLE Device using Custom App without Workaround using nRF Connect
問題總結及背景
作為大學項目的一部分,我們需要使用自定義應用程序連接到藍牙 LE 模塊 (BL654) 以更新特性。
問題是我無法在沒有先做解決方法的情況下連接到我們的模塊。 我能夠毫無問題地搜索設備,並且我們的模塊顯示在搜索中。 我希望該應用程序不必依賴另一個應用程序才能正常工作。
在手機(Pixel 3XL / Pixel 3 / LG G5)的干凈啟動和干凈的操作系統安裝中,我無法連接到我們的模塊。 但是,我可以連接到其他 BLE 設備,例如 Raspberry Pi 和 HTV Vive 基站。
我在 Android Studio Logcat 中收到的錯誤是:
D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=7 device=C2:A1:E0:B3:69:54
然后使用 nRF Connect 連接到不同的設備后,我可以連接到 nRF Connect 中的模塊,然后連接到我的應用程序中的模塊。 Nordic 使固件在板上和 nRF Connect 上運行。 這讓我相信兩者之間正在發生一些特別的事情?
我正在使用標准的 Android 庫進行連接,並且還嘗試使用 RxAndroidBle。
關於這個錯誤和可能的解決方案,我已經研究了近一個月,但無法解決。 任何指導將不勝感激。
這是連接嘗試失敗的Logcat 。 這是使用解決方法后成功連接嘗試的Logcat 。
下面我將展示相關代碼的片段。 如果需要更多代碼,我很樂意分享。
代碼片段
我在 Kotlin Class 文件和 MainActivity.kt 之間進行了代碼拆分,據我所知,我在兩個文件之間傳遞了所有正確的參數。 我是 Kotlin 的初學者,所以盡量放輕松;)
查找藍牙設備(在 mBluetoothLEAdapter.kt 中):
fun findBluetoothDevices(mBluetoothAdapter: BluetoothAdapter?){
// Get and instance of the Bluetooth Low Energy Scanner
scanner = mBluetoothAdapter?.bluetoothLeScanner
// Create search settings object
val mSettings = ScanSettings.Builder().
setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).
setReportDelay(reportDelay).
build()
// Create a scanning filter
val mFilter = ScanFilter.Builder().setDeviceName("AEsir ADC Test").build()
val scannerFilter = arrayListOf<ScanFilter>()
scannerFilter.add(mFilter)
// Stop previous scan if there was one
stopScanningBluetoothDevices()
//Start new scanner
tools.showToast("Scanning...")
scanner?.startScan(null, mSettings, mCallback)
}
掃描回調(在 mBluetoothLEAdapter.kt 中):
inner class MCallBack: ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
stopScanningBluetoothDevices()
tools.showToast("Single Result Found!")
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
stopScanningBluetoothDevices()
tools.showToast("Error on Scan!")
tools.showToast(errorCode.toString())
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
stopScanningBluetoothDevices()
tools.showToast("Batch Results Found!")
scanResults = results
val mAdapter = DeviceListAdapter(activity, scanResults)
val deviceList = activity.findViewById<ListView>(R.id.device_list)
deviceList.adapter = mAdapter
}
}
連接到設備(在 MainActivity.kt 中):
// Runs when an item in the Device List is pressed.
// This initiates a GATT connection to the selected device.
override fun onListPressed(): AdapterView.OnItemClickListener? {
return AdapterView.OnItemClickListener { parent, _, position, _ ->
if (bluetoothGatt != null) {
bluetoothGatt?.disconnect()
bluetoothGatt?.close()
}
val clickedItem = parent.getItemAtPosition(position) as ScanResult
//val device = clickedItem.device
val address = clickedItem.device.address
tools.showToast("Connecting to: $address")
// CONNECTION NOT WORKING. HAVE TO USE nRF Connect to make it work
bluetoothGatt = clickedItem.device.connectGatt(applicationContext, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
}
}
GattCallback(在 MainActivity.kt 中):
inner class GattCallback : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
//If we connected to the GATT server find services on device
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt.discoverServices()
}
else if (status == BluetoothGatt.STATE_CONNECTING) {
tools.showToast("Connecting I am")
}
else if (status == BluetoothGatt.STATE_DISCONNECTED) {
bluetoothGatt?.close()
bluetoothGatt = null
tools.showToast("I got here and closed the connection")
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
bluetoothServices = gatt?.services
}
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
//"Notification"
}
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status)
//Confirm that the characteristic was actually changed
tools.showToast("Characteristic was written!")
}
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
}
override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
}
}
感謝您提供的任何幫助:)
啊,可怕的 GATT 133 錯誤。 這通常表明 Android 的 BLE 堆棧存在問題,並且重置藍牙 - 以及舊設備上的 WiFi - 通常會解決。
您的解決方法有效,因為 Android 允許在一個應用程序中連接的藍牙設備在其他應用程序之間共享。 看起來像一個可怕的安全漏洞,但這是預期的行為。
但是,從您的經驗來看,外圍設備完全有可能具有意外的配置。 也許試試RxCentralBle - Uber 的藍牙 LE 集成庫 - 示例應用程序,看看它是否適用於連接到您的設備。 示例應用程序和庫是開源的,因此您可以根據自己的需要進行調整。
全面披露 - 我是 RxCentralBle 的作者和維護者。
嘗試將報告延遲設置為 0。
您的設置現在應該如下所示
val mSettings = ScanSettings.Builder().
setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).
setReportDelay(0).
build()
您還需要開始使用單個結果回調而不是onBatchScanResults
,這將需要將結果列表存儲在其他位置。
override fun onScanResult(callbackType: Int, result: ScanResult?) {
//add to the list
//adapter.notifyDataSetChanged() if needed
}
我在我的一個應用程序中遇到了這個問題,這似乎是解決方法。
如果向用戶顯示一個列表,這似乎會使列表更新太快,無法通過單擊 go,因此如果出現問題,您可能希望添加自己的延遲更新而不使用setReportDelay
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.