RxAndroidBLE 源碼分析:建立藍(lán)牙連接

1. 得到 外圍藍(lán)牙設(shè)備

想與 外圍的藍(lán)牙設(shè)備相連接,首先得要獲得這個(gè)藍(lán)牙設(shè)備。

官方例子:

bleDevice = SampleApplication.getRxBleClient(this).getBleDevice(macAddress);

具體的實(shí)現(xiàn):
由 RxClient 中的 RxBledeviceProvider 提供具體的 獲取藍(lán)牙設(shè)備的 實(shí)現(xiàn):

Paste_Image.png

具體代碼:

Paste_Image.png
  1. 獲得 BluetoothDevice
 rxBleAdapterWrapper.getRemoteDevice(macAddress);

rxBleAdapterWrapper是 BluetoothAdapter 的包裝,以上代碼本質(zhì)上是:

 public BluetoothDevice getRemoteDevice(String macAddress) {
        return bluetoothAdapter.getRemoteDevice(macAddress);
    }
  1. 包裝 BluetoothDevice---》RxBleDeviceImpl
    包裝了 BluetoothDevice,使其變的更強(qiáng)!
Paste_Image.png

如上,可以通過(guò)包裝后的藍(lán)牙設(shè)備做如下事情:

  1. 建立連接
  2. 觀察連接狀態(tài)
  3. 獲得當(dāng)前的連接狀態(tài)
  4. getName,getMacAddress

2. 觀察 外圍藍(lán)牙設(shè)備的連接狀態(tài)

有了 外圍的藍(lán)牙設(shè)備,我就可以去觀察他了。

官方例子:

// How to listen for connection state changes
bleDevice.observeConnectionStateChanges()
        .compose(bindUntilEvent(DESTROY))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(this::onConnectionStateChange);

深入 RxBleDeviceImpl中的 代碼:

Paste_Image.png

connectionStateSubject:

private final BehaviorSubject<RxBleConnection.RxBleConnectionState> connectionStateSubject = BehaviorSubject.create(DISCONNECTED);

它是個(gè)平臺(tái):

生產(chǎn)者 生產(chǎn)完?yáng)|西,消費(fèi)者過(guò)來(lái)買東西。他們都是通過(guò) subject 這個(gè)平臺(tái)。

subject 有如下幾種實(shí)現(xiàn):

Paste_Image.png

著重看一下:BehaviorSubject

藍(lán)牙的 連接狀態(tài) 事件的生產(chǎn)和發(fā)布 是通過(guò) connectionStateSubject 這個(gè)平臺(tái)的。
下面看一下代碼實(shí)現(xiàn):

Paste_Image.png
  1. 生產(chǎn) 連接中(CONNECTING) 這個(gè)事件。
  2. 生產(chǎn) 連接上了(CONNECTED) 這個(gè)事件。
  3. 生產(chǎn) 斷開(kāi)連接(DISCONNECTED) 這個(gè)事件。

說(shuō)著說(shuō)著就到了與外圍藍(lán)牙設(shè)備的 建立連接~

連接

有了藍(lán)牙設(shè)備,就可以與這個(gè)設(shè)備建立連接了。

RxBleDeviceImpl 中 的connector專門負(fù)責(zé)連接:

Paste_Image.png

核心的連接與斷開(kāi)連接,這些代碼被封裝到:

由RxBleConnectionConnectorOperationsProvider來(lái)管理。

其中建立連接:

Paste_Image.png

繼續(xù):

1. 初步檢查

若藍(lán)牙未啟用,生產(chǎn)一個(gè) 異常對(duì)象:BleDisconnectedException

2. 連接過(guò)程中,考慮各種情況。

考慮情況:未連接上的時(shí)候
(在建立藍(lán)牙連接的時(shí)候,若藍(lán)牙不可用了)

Paste_Image.png

考慮情況:已經(jīng)連接上的時(shí)候
(這時(shí)候,藍(lán)牙斷開(kāi)連接了,也要通知觀察者?。?/p>

Paste_Image.png

考慮情況:用戶不想訂閱這個(gè)連接了。
(針對(duì)這個(gè)連接,用戶不想玩了:斷開(kāi)連接)

下面深入:
將 藍(lán)牙連接這個(gè)操作 進(jìn)行入隊(duì):

Paste_Image.png

RxBleRadioOperationConnect 的具體執(zhí)行什么操作?

 @Override
    protected void protectedRun() {
        final Runnable onConnectionEstablishedRunnable = autoConnect ? emptyRunnable : releaseRadioRunnable;
        final Runnable onConnectCalledRunnable = autoConnect ? releaseRadioRunnable : emptyRunnable;

        getConnectedBluetoothGatt()
                .doOnCompleted(onConnectionEstablishedRunnable::run)
                .subscribe(getSubscriber());

        onConnectCalledRunnable.run();
    }

該流程執(zhí)行完畢后,我們建立了 一個(gè)訂閱關(guān)系:
生產(chǎn)者:建立藍(lán)牙連接,連接成功后,返回此鏈接的 gatt。
消費(fèi)者:再將該 gatt 發(fā)射出去。

再細(xì)看下 getConnectedBluetoothGatt()

當(dāng)你連接成功了會(huì)得到一個(gè) gatt。

核心:建立連接

connectionCompat.connectGatt(bluetoothDevice, autoConnect, rxBleGattCallback.getBluetoothGattCallback())

連接的建立 被封裝到 BleConnectionCompat 類中:

Paste_Image.png

那我們看一下 他們的 connectGatt 方法:

  public BluetoothGatt connectGatt(BluetoothDevice remoteDevice, boolean autoConnect, BluetoothGattCallback bluetoothGattCallback) {

        if (remoteDevice == null) {
            return null;
        }

        if (!autoConnect) {
            return connectGattCompat(bluetoothGattCallback, remoteDevice, false);
        }

        /**
         * Some implementations of Bluetooth Stack have a race condition where autoConnect flag
         * is not properly set before calling connectGatt. That's the reason for using reflection
         * to set the flag manually.
         */

        try {
            RxBleLog.v("Trying to connectGatt using reflection.");
            Object iBluetoothGatt = getIBluetoothGatt(getIBluetoothManager());

            if (iBluetoothGatt == null) {
                RxBleLog.w("Couldn't get iBluetoothGatt object");
                return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
            }

            BluetoothGatt bluetoothGatt = createBluetoothGatt(iBluetoothGatt, remoteDevice);

            if (bluetoothGatt == null) {
                RxBleLog.w("Couldn't create BluetoothGatt object");
                return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
            }

            boolean connectedSuccessfully = connectUsingReflection(bluetoothGatt, bluetoothGattCallback, true);

            if (!connectedSuccessfully) {
                RxBleLog.w("Connection using reflection failed, closing gatt");
                bluetoothGatt.close();
            }

            return bluetoothGatt;
        } catch (NoSuchMethodException
                | IllegalAccessException
                | IllegalArgumentException
                | InvocationTargetException
                | InstantiationException
                | NoSuchFieldException exception) {
            RxBleLog.w(exception, "Error during reflection");
            return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
        }
    }
Paste_Image.png

調(diào)用系統(tǒng)中的 connect 方法進(jìn)行連接。(這個(gè)有空再詳談吧)


Paste_Image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容