亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Android 藍牙通信方式總結

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

1.摘要

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

關鍵詞

(1)Bluetooth

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

(2) UUID

UUID(Universally Unique Identifier):用于標識藍牙服務以及通訊特征訪問屬性,不同的藍牙服務和屬性使用不同的訪問方法。

(3)服務UUID

服務UUID(Service UUID):不同的服務(Service)應該有不同的編號(UUID),用以區(qū)分不同的服務(Service)。

(4)特征值UUID

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

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

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

(5.2)Notify: 通知屬性

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

(5.3)Write: 寫屬性

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

(5.4)WriteWithout Response:寫屬性

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

(6) GATT

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

(7)profile

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

2. Bluetooth Socket

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

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

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

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

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

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

注意:需要BLUETOOTH權限。

2.1 Server端

private static final String UUIDString = "00001101-0000-1000-8000-00805F9B34FB";
//開啟服務器
private class ServerThread extends Thread {
    @Override
    public void run() {
        try {
                /* 創(chuàng)建一個藍牙服務器
                 * 參數(shù)分別:服務器名稱、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);
                //啟動接受數(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)建一個Socket連接:只需要服務器在注冊時的UUID號
            BluetoothDevice device = bluetoothAdapter.getRemoteDevice(remoteAddress);
            BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUIDString));
            //連接
            Message msg2 = new Message();
            msg2.obj = "請稍候,正在連接服務器:" + 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);
            //啟動接受數(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 = "連接服務端異常!斷開連接重新試一試。"+e.getMessage();
            msg.what = CONNECT_SERVER_ERROR;
            linkDetectedHandler.sendMessage(msg);
        }
    }
}

3. Bluetooth GATT

在這里插入圖片描述

在這里插入圖片描述

推薦開源項目:https://github.com/dingpwen/bl_communication https://github.com/zolty-lionheart/bl_communication
以該項目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);
    }
}

參考文獻

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

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

相關文章

最新評論