2016-07-29 211 views
3

因此,我可以在正常情況下連接到BLE設備。我想要做的是處理異常情況,比如當連接到設備失敗或建立的連接丟失(也許它被拋出懸崖或被總線擊中)Android:捕獲BLE連接失敗/斷開連接?

我正在使用CyPress BLE模塊測試這個,我正在做的一個測試是從模塊中去掉電源。但是,onConnectionStateChange永遠不會被調用!我所見過的所有迴應都是成功的關係。它會花費數小時嘗試連接,並永不放棄。我會延遲取消連接嘗試,但是沒有辦法取消BluetoothDevice上的連接嘗試(我知道)!據我所知,它會繼續嘗試,直到電池耗盡。

下面是我的onConnectionStateChange現在在Gatt Callback中的外觀。請注意,我試圖捕捉並記錄任何類型的回調,涉及任何類型的連接狀態更改......永遠不會被調用,除非連接成功。請注意,這是代碼不在活動本身。它在一個由單身人士持有的對象中。 (我想維護多個活動連接)

@Override 
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 
     mGatt = gatt; 
     Logy.CallPrint(LOGY_ENABLE, CLASSNAME, "Status: "+status+ " Newstate: "+newState); 
     switch(status) 
     { 
      case BluetoothGatt.GATT_SUCCESS: 
       mReconnectAttempts = MAX_ATTEMPTS; 

       if(newState == BluetoothGatt.STATE_CONNECTED) 
       { 
        DispatchEvent(Event.Type.BT_ON_CONNECT); 
        bIsConnected = true; 
        gatt.discoverServices(); 
       } else if (newState == BluetoothGatt.STATE_DISCONNECTED) 
       { 
        DispatchEvent(Event.Type.BT_ON_DISCONNECT); 
        bIsConnected = false; 
       } 
       break; 
      default: 
       if(newState == BluetoothGatt.STATE_DISCONNECTED) 
       { 
        bIsConnected = false; 
        if(mReconnectAttempts > 0) 
        { // if we have attempts left, auto attempt to reconnect 
         DispatchEvent(Event.Type.BT_RECONNECTING); 
         mReconnectAttempts--; 
         gatt.connect(); 
         bIsConnected = false; 
        } 
        else 
        { 
         mReconnectAttempts = MAX_ATTEMPTS; 
         DispatchEvent(Event.Type.BT_ON_CONNECT_FAIL); 
         bIsConnected = false; 
        } 
       } else { 
        Logy.CallPrint(LOGY_ENABLE, CLASSNAME, "onConnectionStateChange: Failed?"); 
       } 
     } 

     super.onConnectionStateChange(gatt, status, newState); 
    } 

不能夠檢測斷開是一個問題,其他地方在我的代碼,等,其中我展示一個進度對話框顯示的應用程序被連接到BLE裝置。那麼對話永遠不會消失,因爲事件「連接失敗」永遠不會被拋出。

回答

6

我想你正在尋找的是Bluetooth Supervision timeout這是根據Bluetooth LE specifications

定義之間有兩個接收的數據包的PDU被認爲是連接之前的最長時間失去

參數默認Supervision timeoout在Android上設置爲20秒(取決於Android版本&設備)。例如,here是Android 5.1上的Supervision Timeout的值。

沒有API來設置此參數,那麼你將不得不等待20秒(取決於您的Android版本&設備),以獲得onConnectionStateChange回調與狀態BluetoothGatt.STATE_DISCONNECTED你斷電後您的BLE模塊

2

首先,如果建立的連接斷開,當超過監督超時時間時,應該會收到斷開連接的狀態更改事件。否則,Android中會有一些錯誤。

現在關於連接嘗試。

一旦你使用connectGatt創建了一個BluetoothGatt對象並且指定了自動連接參數爲true或者在現有的BluetoothGatt對象上執行了連接方法,手機將處於一直處於無限期嘗試連接設備的狀態,如果設備因任何原因斷開連接,請重新連接設備,直到您斷開或關閉gatt對象。

因此,如果您想在一段時間後放棄連接,只需設置任何類型的定時器,即在觸發gatt對象時調用斷開連接(或關閉,如果不再需要它)。

另請注意,當newState斷開時,onConnectionStateChange的狀態參數沒有明確定義。在較舊的Android版本中,它通常包含0或133,而在新版本中通常是藍牙標準的斷開原因的錯誤代碼。此外,如果您在沒有獲得連接狀態更改事件的情況下發生斷開連接狀態更改事件,則通常表示內部藍牙堆棧中出現了問題(除非您使用的是非自動連接,在一些超時後斷開狀態改變事件)。然後,我建議您關閉該gatt對象,稍後再試。

+0

我的擔心,雖然是你只有BluetoothDevice並呼籲連接的時間段。沒有BluetoothGatt可以撥打斷開連接。在經過長時間的「嘗試連接到設備」後,沒有調用onConnectionStateChange,並且如果連續嘗試時間過長,我發現沒有明顯的方法取消連接嘗試,這讓我擔心如果嘗試連接到不同的設備通過開始與它連接,這個先前與其他設備的連接嘗試可能最終也會通過! –

4

這個答案與Emil的答案一致。

我編寫了一個測試應用程序與摩托G4運行一個活動播放的Android 6.0.1(MARSHMELLOW:API23)根據萊爾德BL600

我去張貼一些日誌和外設 - 但他們不要格式化得很好 - 所以我只會描述結果。


像往常一樣,外圍廣告和中央掃描,並獲得設備實例。

問題的第一個連接到底如何做沒有說明,但是讓我們假設它是「自動連接」假,形式

mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback); 

(這是連接在測試中使用的唯一風格APP)

這給出了BluetoothGatt一個實例,並在這個問題指出,事件然後異步通過電話彙報, 但也BluetoothGatt上一個實例調用disconnect()即使之前的任何連接事件有發生。

disconnect()狀態的API文檔 - 特別是「

BluetoothGatt.disconnect() 斷開後的部分已建立的連接,或正在進行目前取消連接嘗試。

要釋放GATT資源,斷開後,測試應用程序還那麼總是調用

mBluetoothGatt.close();

這裏有一些不同的情況

  1. device.connectGatt() - 外設廣告 - 建立連接 - 接着是mBluetoothGatt.disconnect()和close()。

    結果:這是一個正常的成功連接,其次是中央設備關閉代碼中的連接。回撥事件按預期收到。當中心在代碼斷開連接時,底層的藍牙服務斷開連接,外設得到斷開連接事件。

  2. device.connectGatt() - 外設廣告 - 已建立連接 - 隨後關閉外設。

    結果:這是一個正常成功的連接,按預期回撥事件,然後由Peripheral斷開連接。Peripheral指示BleGapSvcInit中的首選連接監視超時,並由連接參數更新中的Central確認。在外設斷開連接之後,在連接監視超時之後,中央發生斷開連接事件。 (重複8秒和4秒監督超時)。

  3. device.connectGatt() - 但Peripheral已停止廣告,允許連接嘗試超時。

    結果:(這是問題的特定情況)30秒後,可能是電話上的藍牙服務的連接超時, 有一個onConnectionStateChange事件,指示新連接狀態爲斷開連接 - 帶有(錯誤)狀態133. 還必須記得調用mBluetoothGatt.close()否則會發生接口泄漏,並在下一個客戶機接口上進行後續連接。
    。 device.connectGatt() - 外設仍在廣告中,但使用mBluetoothGatt.disconnect()和close()關閉200ms後連接被取消。有時,底層的藍牙服務實際上連接到了外圍設備;有些時候,(大約1/10) 底層的藍牙服務實際上確實連接到了外圍設備;看到一個連接,然後斷開連接;即使應用程序未在回撥中看到 這些事件。有時候,就應用而言,應用程序已斷開連接,底層的藍牙電話服務 連接到外設 - 並在測試中保持連接幾分鐘,直到我超時! - 並關閉BT服務或外圍設備。

+0

#4讓我的生活變得非常困難。我一次連接多達7臺設備,當您使用這麼多設備時,每10臺中就有一臺會發生。我很高興看到所有這些類型記錄在這裏。 –