欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android 藍(lán)牙通信方式總結(jié)

 更新時(shí)間:2021年05月06日 10:32:53   作者:zolty  
這篇文章主要介紹了詳解Android 藍(lán)牙通信方式總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1.摘要

Android手機(jī)間通過藍(lán)牙方式進(jìn)行通信,有兩種常見的方式,一種是socket方式,另一種是通過Gatt Server(Android 5.0以后)通信,socket方式最為簡單,但是很多低功耗的藍(lán)牙設(shè)備,如單片機(jī)上的藍(lán)牙模塊可能不支持;而Gatt方式相對(duì)比較復(fù)雜。其實(shí)無論是socket方式還是Gatt,Android設(shè)備間藍(lán)牙通信都是一種C/S(client-server)模式。
本文基于兩種通信方式,進(jìn)行詳細(xì)展開,并推薦了開源項(xiàng)目,建議配合學(xué)習(xí)。

關(guān)鍵詞

(1)Bluetooth

藍(lán)牙(Bluetooth):藍(lán)牙,是一種支持設(shè)備短距離通信(一般10m內(nèi))的無線電技術(shù),能在包括移動(dòng)電話、PDA、無線耳機(jī)、筆記本電腦、相關(guān)外設(shè)等眾多設(shè)備之間進(jìn)行無線信息交換。利用“藍(lán)牙”技術(shù),能夠有效地簡化移動(dòng)通信終端設(shè)備之間的通信,也能夠成功地簡化設(shè)備與因特網(wǎng)Internet之間的通信,從而使數(shù)據(jù)傳輸變得更加迅速高效,為無線通信拓寬道路。

(2) UUID

UUID(Universally Unique Identifier):用于標(biāo)識(shí)藍(lán)牙服務(wù)以及通訊特征訪問屬性,不同的藍(lán)牙服務(wù)和屬性使用不同的訪問方法。

(3)服務(wù)UUID

服務(wù)UUID(Service UUID):不同的服務(wù)(Service)應(yīng)該有不同的編號(hào)(UUID),用以區(qū)分不同的服務(wù)(Service)。

(4)特征值UUID

特征值UUID(Characteristic UUID):特性(Characteristic) 是依附于某個(gè)服務(wù)(Service)的

(5)屬性(Property) (5.1)Read: 讀屬性

Read: 讀屬性,具有這個(gè)屬性的特性是可讀的,也就是說這個(gè)屬性允許手機(jī)來讀取一些信息。手機(jī)可以發(fā)送指令來讀取某個(gè)具有讀屬性UUID的信息。

(5.2)Notify: 通知屬性

Notify: 通知屬性, 具有這個(gè)屬性的特性是可以發(fā)送通知的,也就是說具有這個(gè)屬性的特性(Characteristic)可以主動(dòng)發(fā)送信息給手機(jī)。

(5.3)Write: 寫屬性

Write: 寫屬性, 具有這個(gè)屬性的特性是可以接收寫入數(shù)據(jù)的。通常手機(jī)發(fā)送數(shù)據(jù)給藍(lán)模塊就是通過這個(gè)屬性完成的。這個(gè)屬性在Write 完成后,會(huì)發(fā)送寫入完成結(jié)果的反饋給手機(jī),然后手機(jī)再可以寫入下一包或處理后續(xù)業(yè)務(wù),這個(gè)屬性在寫入一包數(shù)據(jù)后,需要等待應(yīng)用層返回寫入結(jié)果,速度比較慢。

(5.4)WriteWithout Response:寫屬性

WriteWithout Response:寫屬性,從字面意思上看,只是寫,不需要返回寫的結(jié)果,這個(gè)屬性的特點(diǎn)是不需要應(yīng)用層返回,完全依靠協(xié)議層完成,速度快,但是寫入速度超過協(xié)議處理速度的時(shí)候,會(huì)丟包。

(6) GATT

GATT(Generic Attribute Profile):中文名叫通用屬性協(xié)議,它定義了services和characteristic兩種東西來完成低功耗藍(lán)牙設(shè)備之間的數(shù)據(jù)傳輸。它是建立在通用數(shù)據(jù)協(xié)議Attribute Protocol (ATT),之上的,ATT把services和characteristic以及相關(guān)的數(shù)據(jù)保存在一張簡單的查找表中,該表使用16-bit的id作為索引。

(7)profile

profile可以理解為一種規(guī)范,一個(gè)標(biāo)準(zhǔn)的通信協(xié)議,它存在于從機(jī)中。藍(lán)牙組織規(guī)定了一些標(biāo)準(zhǔn)的profile,例如 HID OVER GATT ,防丟器 ,心率計(jì)等。每個(gè)profile中會(huì)包含多個(gè)service,每個(gè)service代表從機(jī)的一種能力。

2. Bluetooth Socket

推薦開源項(xiàng)目:https://github.com/Zweo/Bluetooth https://github.com/zolty-lionheart/Bluetooth
以該項(xiàng)目demo為例介紹
藍(lán)牙端口監(jiān)聽接口和TCP端口類似:Socket和ServerSocket類。在服務(wù)器端,使用BluetoothServerSocket類來創(chuàng)建一個(gè) 監(jiān)聽服務(wù)端口。當(dāng)一個(gè)連接被BluetoothServerSocket所接受,它會(huì)返回一個(gè)新的BluetoothSocket來管理該連接。在客戶 端,使用一個(gè)單獨(dú)的BluetoothSocket類去初始化一個(gè)外接連接和管理該連接。

最通常使用的藍(lán)牙端口是RFCOMM,它是被Android API支持的類型。RFCOMM是一個(gè)面向連接,通過藍(lán)牙模塊進(jìn)行的數(shù)據(jù)流傳輸方式,它也被稱為串行端口規(guī)范(Serial Port Profile,SPP)。

為了創(chuàng)建一個(gè)BluetoothSocket去連接到一個(gè)已知設(shè)備,使用方法 BluetoothDevice.createRfcommSocketToServiceRecord()。然后調(diào)用connect()方法去嘗試一個(gè) 面向遠(yuǎn)程設(shè)備的連接。這個(gè)調(diào)用將被阻塞指導(dǎo)一個(gè)連接已經(jīng)建立或者該鏈接失效。

為了創(chuàng)建一個(gè)BluetoothSocket作為服務(wù)端(或者“主機(jī)”),查看BluetoothServerSocket文檔。

每當(dāng)該端口連接成功,無論它初始化為客戶端,或者被接受作為服務(wù)器端,通過getInputStream()和getOutputStream()來打開IO流,從而獲得各自的InputStream和OutputStream對(duì)象

BluetoothSocket類線程安全。特別的,close()方法總會(huì)馬上放棄外界操作并關(guān)閉服務(wù)器端口。

注意:需要BLUETOOTH權(quán)限。

2.1 Server端

private static final String UUIDString = "00001101-0000-1000-8000-00805F9B34FB";
//開啟服務(wù)器
private class ServerThread extends Thread {
    @Override
    public void run() {
        try {
                /* 創(chuàng)建一個(gè)藍(lán)牙服務(wù)器
                 * 參數(shù)分別:服務(wù)器名稱、UUID   */
            mServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM, UUID.fromString(UUIDString));
            while (true){
                Log.d("server", "wait cilent connect...");
                Message msg = new Message();
                msg.obj = "請稍候,正在等待客戶端的連接...";
                msg.what = WAITING_FOR_CLIENT;
                linkDetectedHandler.sendMessage(msg);
                /* 接受客戶端的連接請求 */
                BluetoothSocket socket = mServerSocket.accept();
                socketMap.put(socket.getRemoteDevice().getAddress(), socket);
//                  remoteDeviceMap.put(socket.getRemoteDevice().getAddress(),socket.getRemoteDevice());
                Log.d("server", "accept success !");
                Message msg2 = new Message();
                String info = "客戶端已經(jīng)連接上!可以發(fā)送信息。";
                msg2.obj = info;
                msg.what = CONNECTED_CLIENT;
                linkDetectedHandler.sendMessage(msg2);
                //啟動(dòng)接受數(shù)據(jù)
                ReadThread mreadThread = new ReadThread(socket.getRemoteDevice().getAddress());
                readThreadMap.put(socket.getRemoteDevice().getAddress(),mreadThread);
                mreadThread.start();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 Server

//開啟客戶端
private class ClientThread extends Thread {
    private String remoteAddress;
    public ClientThread(String remoteAddress) {
        this.remoteAddress = remoteAddress;
    }
    @Override
    public void run() {
        try {
            //創(chuàng)建一個(gè)Socket連接:只需要服務(wù)器在注冊時(shí)的UUID號(hào)
            BluetoothDevice device = bluetoothAdapter.getRemoteDevice(remoteAddress);
            BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUIDString));
            //連接
            Message msg2 = new Message();
            msg2.obj = "請稍候,正在連接服務(wù)器:" + remoteAddress;
            msg2.what = IS_CONNECTING_SERVER;
            linkDetectedHandler.sendMessage(msg2);
            socket.connect();
            socketMap.put(remoteAddress, socket);
            Message msg = new Message();
            msg.obj = remoteAddress;
            msg.what = CONNECTED_SERVER;
            linkDetectedHandler.sendMessage(msg);
            //啟動(dòng)接受數(shù)據(jù)
            ReadThread mreadThread = new ReadThread(remoteAddress);
            readThreadMap.put(remoteAddress,mreadThread);
            mreadThread.start();
        } catch (IOException e) {
            e.printStackTrace();
            socketMap.remove(remoteAddress);
            Log.e("connect", e.getMessage(), e);
            Message msg = new Message();
            msg.obj = "連接服務(wù)端異常!斷開連接重新試一試。"+e.getMessage();
            msg.what = CONNECT_SERVER_ERROR;
            linkDetectedHandler.sendMessage(msg);
        }
    }
}

3. Bluetooth GATT

在這里插入圖片描述

在這里插入圖片描述

推薦開源項(xiàng)目:https://github.com/dingpwen/bl_communication https://github.com/zolty-lionheart/bl_communication
以該項(xiàng)目demo為例介紹

3.1 Server

private fun setupServer() {
    val gattService = BluetoothGattService(Constants.BLE_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
    val characteristicRead = BluetoothGattCharacteristic(Constants.BLE_READ_UUID, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ)
    val descriptor = BluetoothGattDescriptor(Constants.BLE_DESC_UUID, BluetoothGattCharacteristic.PERMISSION_WRITE)
    characteristicRead.addDescriptor(descriptor)
    gattService.addCharacteristic(characteristicRead)
    val characteristicWrite = BluetoothGattCharacteristic(Constants.BLE_WRITE_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE or
            BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
            BluetoothGattCharacteristic.PERMISSION_WRITE)
    gattService.addCharacteristic(characteristicWrite)
    Log.d("wenpd", "startGattServer:stagattServicetus=$gattService")
    mGattServer.addService(gattService)
}

3.2 Client

private class GattClientCallback extends BluetoothGattCallback {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
        if (status == BluetoothGatt.GATT_FAILURE) {
            disconnectGattServer();
            return;
        } else if (status != BluetoothGatt.GATT_SUCCESS) {
            disconnectGattServer();
            return;
        }
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            mConnected = true;
            gatt.discoverServices();
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            disconnectGattServer();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
        Log.d(TAG, "onServicesDiscovered status:" + status);
        if (status != BluetoothGatt.GATT_SUCCESS) {
            return;
        }
        BluetoothGattService service = gatt.getService(Constants.SERVICE_UUID);
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(Constants.CHARACTERISTIC_UUID);
        characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
        mInitialized = gatt.setCharacteristicNotification(characteristic, true);
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        byte[] messageBytes = characteristic.getValue();
        /*for(int i = 0, j = messageBytes.length -1; i < j; ++i, --j) {
            byte temp = messageBytes[i];
            messageBytes[i] = messageBytes[j];
            messageBytes[j] = temp;
        }*/
        String messageString = new String(messageBytes, StandardCharsets.UTF_8);
        Log.d(TAG,"Received message: " + messageString);
        setReceivedData(messageString);
    }
}

參考文獻(xiàn)

1.Android Phone藍(lán)牙通信方式總結(jié)(Socket與Gatt)
2.Bluetooth之BluetoothSocket
3.全面且簡單明了的藍(lán)牙服務(wù)及UUID介紹
4.Android BLE藍(lán)牙開發(fā)-讀寫數(shù)據(jù) 獲取UUID

到此這篇關(guān)于詳解Android 藍(lán)牙通信方式總結(jié)的文章就介紹到這了,更多相關(guān)Android 藍(lán)牙通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論