国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android Ble藍牙App(五)數(shù)據(jù)操作

這篇具有很好參考價值的文章主要介紹了Android Ble藍牙App(五)數(shù)據(jù)操作。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

??關(guān)于低功耗藍牙的服務(wù)、特性、屬性、描述符都已經(jīng)講清楚了,而下面就是使用這些知識進行數(shù)據(jù)的讀取、寫入、通知等操作。

目錄

  • Ble藍牙App(一)掃描
  • Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù)
  • Ble藍牙App(三)特性和屬性
  • Ble藍牙App(四)UI優(yōu)化和描述符
  • Ble藍牙App(五)數(shù)據(jù)操作

正文

??首先要做的就是根據(jù)操作內(nèi)容進行相應(yīng)的處理,目前常見的操作有Read、Write、Write no response、Notify和Indicate。

一、操作內(nèi)容處理

??首先要修改MainActivity中的onPropertyOperate()函數(shù),

    override fun onPropertyOperate(characteristic: BluetoothGattCharacteristic, operateName: String) {
        if (!bleCore.isConnected()) showMsg("設(shè)備已斷開連接")
        when (operateName) {
            READ -> {}
            WRITE, WRITE_NO_RESPONSE -> {}
            NOTIFY, INDICATE -> {}
            BROADCAST, AUTHENTICATED_SIGNED_WRITES, EXTENDED_PROPERTIES -> showMsg(operateName)
        }
    }

這里著重看剛才提到的5個操作,在操作之前我們最好判斷一下當(dāng)前是否處于連接中,在BleCore中增加isConnected()函數(shù),代碼如下所示:

	fun isConnected() = mIsConnected

二、讀取數(shù)據(jù)

① 概念

??在BLE(Bluetooth Low Energy)通信中,Ble Read(讀操作)是一種用于從BLE服務(wù)器設(shè)備讀取數(shù)據(jù)的操作。

當(dāng)一個BLE設(shè)備(稱為客戶端)需要獲取另一個BLE設(shè)備(稱為服務(wù)器)上的數(shù)據(jù)時,可以使用Ble Read操作??蛻舳讼蚍?wù)器發(fā)送讀取請求,并等待服務(wù)器返回所請求的數(shù)據(jù)。

Ble Read操作具有以下特點:

  1. 請求-回復(fù)模式:Ble Read操作是一種請求-回復(fù)模式的操作,客戶端向服務(wù)器發(fā)送讀取請求,服務(wù)器則回復(fù)所請求的數(shù)據(jù)。這種模式保證了數(shù)據(jù)傳輸?shù)目煽啃院晚樞蛐浴?/p>

  2. 單次數(shù)據(jù)傳輸:Ble Read操作一次只能讀取一個數(shù)據(jù)值或一個數(shù)據(jù)塊。如果需要讀取多個數(shù)據(jù)值,客戶端需要連續(xù)發(fā)送多個讀取請求。

  3. 數(shù)據(jù)的訪問權(quán)限:Ble Read操作只能讀取具有權(quán)限允許的數(shù)據(jù)。服務(wù)器可以設(shè)定數(shù)據(jù)的訪問權(quán)限,例如只允許讀取、只允許寫入、或者讀寫均允許。

??需要注意的是,Read操作可能會引入一定的延遲,因為客戶端需要等待服務(wù)器的響應(yīng)。此外,Read操作的成功取決于服務(wù)器是否支持讀取請求,并且客戶端是否具有讀取權(quán)限。

② 實操

??當(dāng)特性擁有Read的屬性時,我們就可以讀取特性的value,在的BleCoreBleGattCallback中,重寫onCharacteristicRead()函數(shù),代碼如下所示:

        /**
         * 讀取特性回調(diào) Android 13及以上使用
         */
        override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, status: Int) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            deviceInfo("讀取特性值(Android 13及以上):${BleUtils.bytesToHex(value, true)}")
        }

        /**
         * 讀取特性回調(diào) Android 12及以下使用
         */
        @Deprecated("Deprecated in Java")
        override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            deviceInfo("讀取特性值(Android 12及以下):${BleUtils.bytesToHex(characteristic.value, true)}")
        }

??bytesToHex()是將byte[]轉(zhuǎn)成Hex的函數(shù),還有hexToBytes的函數(shù),我們在BleUtils中增加這兩個函數(shù),代碼如下所示:

    /**
     * byte[] to hex
     * @param isAdd 是否添加 0x 頭
     */
    fun bytesToHex(byteArray: ByteArray, isAdd: Boolean = false): String {
        val hexChars = "0123456789ABCDEF"
        val hexString = StringBuilder()
        for (byte in byteArray) {
            val value = byte.toInt() and 0xFF
            val firstIndex = value shr 4 and 0x0F
            val secondIndex = value and 0x0F
            hexString.append(hexChars[firstIndex])
            hexString.append(hexChars[secondIndex])
        }
        return (if (isAdd) "0x" else "" ) + hexString.toString()
    }

    /**
     * hex to byte[]
     */
    fun hexToBytes(hexString: String): ByteArray {
        val cleanHexString = hexString.replace("\\s".toRegex(), "")
        val byteArray = ByteArray(cleanHexString.length / 2)
        for (i in byteArray.indices) {
            val index = i * 2
            val byteString = cleanHexString.substring(index, index + 2)
            val byteValue = byteString.toInt(16).toByte()
            byteArray[i] = byteValue
        }
        return byteArray
    }

??讀取特性之后如果狀態(tài)正常,我們就顯示一下讀取的內(nèi)容,當(dāng)我們調(diào)用Gatt的readCharacteristic()函數(shù)時就會觸發(fā)這個回調(diào)。下面在BleCore中增加readCharacteristic()函數(shù),代碼如下所示:

    fun readCharacteristic(characteristic: BluetoothGattCharacteristic) {
        deviceInfo("讀取特性: ${BleUtils.getShortUUID(characteristic.uuid)}")
        mGatt?.readCharacteristic(characteristic)
    }

然后修改onPropertyOperate()函數(shù),代碼如下所示:

    override fun onPropertyOperate(characteristic: BluetoothGattCharacteristic, operateName: String) {
        when (operateName) {
            READ -> bleCore.readCharacteristic(characteristic)
            ...
        }
    }

下面我們運行一下:

Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互

三、寫入數(shù)據(jù)

??讀取數(shù)據(jù)寫好了,下面我們來看寫入數(shù)據(jù),寫入數(shù)據(jù)要看寫入的方式,有Write和Wirte No Response,我們先了解這兩種方式的區(qū)別:

① 概念

??在BLE通信中,有兩種常用的寫操作方式:Ble Write(帶回復(fù)的寫操作)和Write No Response(無回復(fù)的寫操作)。

  1. Ble Write(帶回復(fù)的寫操作):當(dāng)一個BLE設(shè)備(稱為客戶端)想要向另一個BLE設(shè)備(稱為服務(wù)器)發(fā)送數(shù)據(jù)時,可以使用Ble Write操作。客戶端向服務(wù)器發(fā)送數(shù)據(jù)并等待服務(wù)器發(fā)送確認(rèn)回復(fù)(Acknowledgment)來表示數(shù)據(jù)已經(jīng)被成功接收。這種寫操作是一種可靠的方式,確保數(shù)據(jù)傳輸?shù)目煽啃浴?/p>

  2. Write No Response(無回復(fù)的寫操作):在某些情況下,客戶端發(fā)送的數(shù)據(jù)并不需要服務(wù)器的確認(rèn)回復(fù),或者在時間上要求更加緊湊的傳輸。這時可以使用Write No Response操作??蛻舳讼蚍?wù)器發(fā)送數(shù)據(jù)后,并不會等待服務(wù)器的確認(rèn)回復(fù)。這種寫操作通常用于實時傳輸?shù)炔恍枰_認(rèn)的數(shù)據(jù),以減少通信延遲和增加通信吞吐量。

??需要注意的是,Write No Response操作在數(shù)據(jù)傳輸過程中不提供任何保障機制,例如數(shù)據(jù)的可靠性、順序性或冪等性等。因此,使用Write No Response操作時需要確保應(yīng)用場景的需求和通信的可靠性。

② 實操

??寫入數(shù)據(jù)需要有一個輸入框,因此我就寫了一個彈窗來進行操作,首先寫彈窗布局,在layout下新建一個dialog_write_data.xml,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white">

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:title="寫入數(shù)據(jù)" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/data_layout"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        app:boxStrokeColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:prefixText="0x">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/et_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="HEX數(shù)據(jù)"
            android:inputType="text|textCapCharacters"
            android:lines="1"
            android:singleLine="true" />
    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/btn_negative"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="18dp"
        android:layout_weight="1"
        android:text="取消"
        app:layout_constraintEnd_toStartOf="@+id/btn_positive"
        app:layout_constraintTop_toTopOf="@+id/btn_positive" />

    <Button
        android:id="@+id/btn_positive"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="16dp"
        android:layout_weight="1"
        android:text="發(fā)送"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/data_layout"
        app:layout_constraintTop_toBottomOf="@+id/data_layout" />

</androidx.constraintlayout.widget.ConstraintLayout>

??布局內(nèi)容比較簡單,只需要一個輸入框兩個按鈕即可,下面我們在MainActivity中寫一個函數(shù)來加載這個布局xml顯示彈窗,代碼如下所示:

    /**
     * 顯示寫入數(shù)據(jù)彈窗
     */
    private fun showWriteDataDialog(characteristic: BluetoothGattCharacteristic, operateName: String) {
        val dialog = BottomSheetDialog(this, R.style.BottomSheetDialogStyle)
        val writeDataBinding = DialogWriteDataBinding.inflate(layoutInflater)
        writeDataBinding.toolbar.title = if (operateName == WRITE) "寫入數(shù)據(jù)" else "寫入無需響應(yīng)數(shù)據(jù)"
        writeDataBinding.btnPositive.setOnClickListener {
            val inputData = writeDataBinding.etData.text.toString()
            if (inputData.isEmpty()) {
                writeDataBinding.dataLayout.error = "請輸入數(shù)據(jù)"
                return@setOnClickListener
            }
            if (!BleUtils.isHexFormat(inputData)) {
                writeDataBinding.dataLayout.error = "請輸入有效數(shù)據(jù)"
                return@setOnClickListener
            }
            bleCore.writeCharacteristic(characteristic, inputData, operateName)
            dialog.dismiss()
        }
        writeDataBinding.btnNegative.setOnClickListener {
            dialog.dismiss()
        }
        dialog.setContentView(writeDataBinding.root)
        dialog.show()
    }

??在彈窗中,根據(jù)傳入的操作名判斷要以什么方式寫入數(shù)據(jù),同時對寫入的數(shù)據(jù)進行了格式校驗,在BleUtils中增加函數(shù),代碼如下所示:

fun isHexFormat(str: String) = Regex("^([\\dA-Fa-f]{2})+$").matches(str)

??當(dāng)檢查數(shù)據(jù)無誤之后我們就可以寫入數(shù)據(jù)了,調(diào)用bleCore.writeCharacteristic(characteristic, inputData, operateName),在BleCore中增加這個函數(shù),代碼如下所示:

    /**
     * 寫入特性
     * @param characteristic 特性
     * @param data Hex數(shù)據(jù)
     * @param operateName 操作名,決定寫入的是 Write 還是 Write No Response
     */
    fun writeCharacteristic(characteristic: BluetoothGattCharacteristic, data: String, operateName: String) {
        deviceInfo("寫入特性:${BleUtils.getShortUUID(characteristic.uuid)},value:0x$data")
        //寫入類型
        val writeType = if (operateName == BleConstant.WRITE) BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT else BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE
        //寫入數(shù)據(jù)
        val byteArray = BleUtils.hexToBytes(data)
        //根據(jù)Android版本進行不同的寫入方式 Android 13及以上和以下不同
        val executionResult = if (isAndroid13()) {
            mGatt?.writeCharacteristic(characteristic, byteArray, writeType) == BluetoothStatusCodes.SUCCESS
        } else {
            characteristic.writeType = writeType
            characteristic.value = byteArray
            mGatt?.writeCharacteristic(characteristic)
        }
        //執(zhí)行寫入動作成功不代表寫入數(shù)據(jù)成功,執(zhí)行寫入動作失敗,寫入數(shù)據(jù)一定失敗
        deviceInfo(if (executionResult == true)  "執(zhí)行寫入動作成功" else "執(zhí)行寫入動作失敗")
    }

??這個函數(shù)相對的內(nèi)容多一些,首先是根據(jù)操作名得到寫入的類型,然后獲取寫入的數(shù)據(jù),再根據(jù)Android的版本去寫入數(shù)據(jù),最終調(diào)用Gatt的writeCharacteristic()函數(shù)進行寫入,寫入屬于一個執(zhí)行動作,有失敗的可能性,可以根據(jù)返回值進行判斷,Android13以前返回的是Boolean,Android13及以上返回的是Int,這里要注意一下。執(zhí)行之后如果成功了,則會觸發(fā)GattCallback的onCharacteristicWrite()回調(diào),下面在BleGattCallback中重寫這個函數(shù),代碼如下所示:

        override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            if (BleUtils.isAndroid13()) {
                gatt.readCharacteristic(characteristic)
            } else {
                deviceInfo("寫入成功:${BleUtils.bytesToHex(characteristic.value)}")
            }
        }

??這個函數(shù)中,如果是Android 13及以上版本,寫入回調(diào)中的value是null,需要通過readCharacteristic()函數(shù)去獲取寫入的值,但是要確保這個特性有Read屬性,否則讀取不了,這個地方也是我覺得不合理得地方,也有可能是我沒找到對應(yīng)得方式吧。最后我們修改MainActivity中的onPropertyOperate()函數(shù)中的代碼,如下所示:

    override fun onPropertyOperate(characteristic: BluetoothGattCharacteristic, operateName: String) {
        when (operateName) {
            WRITE, WRITE_NO_RESPONSE -> showWriteDataDialog(characteristic, operateName)
            ...
        }
    }

??最后我們再修復(fù)一個bug,沒錯,前面寫的時候這個bug忽略掉了,那就是在CharacteristicAdapteronBindViewHolder()函數(shù)中,之前在這里對屬性的點擊進行了回調(diào),當(dāng)時是傳進去一個特性,和一個操作名稱,如圖所示
Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互
??這里通過position獲取到特性,而這里的position是屬性適配器,而我們要的是特性適配器的position,這樣做的問題就在于使用的時候如果只有一個屬性的話,那么無論有幾個特性,position都是0,也是在調(diào)試中發(fā)現(xiàn)的這個問題,改完之后代碼如下所示:

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val characteristic = characteristics[position]
        val characteristicName = BleUtils.getCharacteristicsName(characteristic.uuid)
        holder.binding.tvCharacterName.text = characteristicName
        holder.binding.tvCharacterUuid.text = if (characteristicName != UNKNOWN_CHARACTERISTICS) BleUtils.getShortUUID(characteristic.uuid) else characteristic.uuid.toString()
        //加載特性下的屬性
        holder.binding.rvProperty.apply {
            layoutManager = LinearLayoutManager(context).apply { orientation = LinearLayoutManager.HORIZONTAL }
            val properties: List<String> = BleUtils.getProperties(characteristic.properties)
            adapter = PropertyAdapter(properties, object : OnItemClickListener {
                //點擊屬性
                override fun onItemClick(view: View?, position: Int) { callback.onPropertyOperate(characteristic, properties[position]) }
            })
        }
        //加載特性下的描述
        if (characteristic.descriptors.isEmpty()) {
            holder.binding.layDescriptors.visibility = View.GONE
            return
        }
        holder.binding.rvDescriptor.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = DescriptorAdapter(characteristic.descriptors)
        }
    }

為了方便查看動作,我們在修改一下BleCore中的deviceInfo()函數(shù)代碼,加一個日志打印,代碼如下所示:

        private fun deviceInfo(info: String) {
            Log.d(TAG, "deviceInfo: $info")
            mBleCallback?.deviceInfo(info)
        }

下面運行一下:

Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互

日志如下所示:

Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互

四、打開通知

??實際上打開通知的意義就是能夠收到藍牙設(shè)備返回的數(shù)據(jù),先了解以下相關(guān)的概念知識。

一、概念

??Ble Enable Notify是指在藍牙低功耗(BLE)通信中使能通知功能的操作。當(dāng)設(shè)備之間建立了藍牙連接后,設(shè)備可以通過特征(Characteristic)來交換數(shù)據(jù)。通知(Notification)是一種特征的屬性,允許一個設(shè)備向另一個設(shè)備發(fā)送數(shù)據(jù),而不需要另一個設(shè)備主動請求。

??當(dāng)一個設(shè)備使能了通知功能(Enable Notify),它就可以向另一個設(shè)備發(fā)送通知,另一個設(shè)備只需要注冊監(jiān)聽這個特征的通知即可接收到數(shù)據(jù)。這樣可以實現(xiàn)數(shù)據(jù)的異步傳輸,一旦數(shù)據(jù)發(fā)生變化,發(fā)送方會自動發(fā)出通知,接收方就可以及時獲取到最新的數(shù)據(jù)。在BLE開發(fā)中,通常需要通過操作特征的屬性來使能或禁用通知功能。

二、實操

??下面我們來實際操作一下,首先在BleCore中增加一個函數(shù),代碼如下所示:

    /**
     * 開啟或者關(guān)閉通知
     * @param characteristic 特性
     * @param descriptorUuid 描述UUID
     * @param operateName 操作名, 決定通過那種方式開啟通知
     */
    fun notifyEnable(characteristic: BluetoothGattCharacteristic, descriptorUuid: UUID, operateName: String) {
        //設(shè)置特性通知,這一點很重要
        if (mGatt?.setCharacteristicNotification(characteristic,true) == false) return
        //描述
        val descriptor = characteristic.getDescriptor(descriptorUuid)
        //寫入描述值
        val value = if (!mIsEnabled) {
            if (operateName == BleConstant.INDICATE) BluetoothGattDescriptor.ENABLE_INDICATION_VALUE else BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
        } else {
            BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
        }
        val executionResult = if (isAndroid13()) {
            mGatt?.writeDescriptor(descriptor, value) == BluetoothStatusCodes.SUCCESS
        } else {
            descriptor.value = value
            mGatt?.writeDescriptor(descriptor)
        }
        deviceInfo((if (executionResult == true)  "執(zhí)行啟用動作成功" else "執(zhí)行啟用動作失敗") + ",value: ${BleUtils.bytesToHex(value, true)}" )
    }

??因為當(dāng)前的項目環(huán)境是基于Android13,所在在藍牙的一些API處理上,我們都要考慮兼容的問題,我覺得奇怪的是,為什么不在Android12的版本中順便加上去這些改動的API,也不重要,開發(fā)者就是這個命,這里的代碼實際上比較簡單,就是根據(jù)操作名進行enable的方式,通過一個變量mIsEnabled來決定你是打開通知還是關(guān)閉通知,這個變量我們定義在companion object中,代碼如下所示:

    companion object {
    	...
        /**
         * 是否開啟通知
         */
        private var mIsEnabled = false
	}

??調(diào)用writeDescriptor()會觸發(fā)描述符寫入回調(diào),在BleGattCallback中增加這個回調(diào),代碼如下所示:

        /**
         * 描述符寫入回調(diào)
         */
        override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            if (BleUtils.isAndroid13()) {
                gatt.readDescriptor(descriptor) //讀取描述符
            } else {
                mIsEnabled = !descriptor.value.contentEquals(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)
                deviceInfo("寫入描述符成功:${BleUtils.bytesToHex(descriptor.value, true)}")
            }
        }

??在回調(diào)中,處理mIsEnabled的賦值,因為在Android 13中沒有辦法直接獲取描述符結(jié)果,而是需要通過readDescriptor()函數(shù)獲取,使用這個函數(shù),則會觸發(fā)另一個回調(diào)函數(shù),同樣是在BleGattCallback中增加這個回調(diào),代碼如下所示:

        /**
         * 讀取描述符回調(diào) Android 13及以上使用
         */
        override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            mIsEnabled = !value.contentEquals(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)
            deviceInfo("讀取描述符成功(Android 13及以上使用):${BleUtils.bytesToHex(value, true)}")
        }
        
        /**
         * 讀取描述符回調(diào) Android 12及以上下使用
         */
        @Deprecated("Deprecated in Java")
        override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
            if (status != BluetoothGatt.GATT_SUCCESS) return
            mIsEnabled = !descriptor.value.contentEquals(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE)
            deviceInfo("讀取描述符成功(Android 12及以下使用):${BleUtils.bytesToHex(descriptor.value, true)}")
        }

??關(guān)于mIsEnabled的參數(shù)我們還需要修改一下一個地方,那就是在連接設(shè)備之后如果發(fā)現(xiàn)mIsEnabled 為true,我們改成false。

    fun connect(device: BluetoothDevice) {
        deviceInfo("連接中...")
        if (mIsEnabled) mIsEnabled = false
        ...
    }

然后我們再修改一下MainActivity中的onPropertyOperate()函數(shù),代碼如下所示:

    /**
     * 屬性操作
     */
    override fun onPropertyOperate(characteristic: BluetoothGattCharacteristic, operateName: String) {
        if (!bleCore.isConnected()) showMsg("設(shè)備已斷開連接")
        Log.d("TAG", "onPropertyOperate: ${characteristic.uuid}")
        when (operateName) {
            READ -> bleCore.readCharacteristic(characteristic)
            WRITE, WRITE_NO_RESPONSE -> showWriteDataDialog(characteristic, operateName)
            NOTIFY, INDICATE -> bleCore.notifyEnable(characteristic, characteristic.descriptors[0].uuid, operateName)
            BROADCAST, AUTHENTICATED_SIGNED_WRITES, EXTENDED_PROPERTIES -> showMsg(operateName)
        }
    }

那么到現(xiàn)在為止我們就寫好了基本的操作方式。

三、收到數(shù)據(jù)

??下面我們寫一下接收通知的回調(diào),同樣是在BleGattCallback中增加這個回調(diào),代碼如下所示:

        /**
         * 收到數(shù)據(jù)回調(diào) Android 13及以上使用
         */
        override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray) {
            deviceInfo("收到特性值(Android 13及以上):${BleUtils.getShortUUID(characteristic.uuid)}${BleUtils.bytesToHex(value, true)}")
        }

        /**
         * 收到數(shù)據(jù)回調(diào) Android 12及以下使用
         */

        @Deprecated("Deprecated in Java")
        override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
            deviceInfo("收到特性值(Android 12及以下):${BleUtils.getShortUUID(characteristic.uuid)}${BleUtils.bytesToHex(characteristic.value, true)}")
        }

??下面我們運行一下,這里你要以自己的實際設(shè)備為準(zhǔn),比如我用的這個設(shè)備,包括數(shù)據(jù)的交互都是廠商自定義的,下面我先開啟Notify然后寫入數(shù)據(jù),再看是否有數(shù)據(jù)返回。

Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互

??我們再看一下控制臺日志

Android Ble藍牙App(五)數(shù)據(jù)操作,藍牙,Ble數(shù)據(jù)交互,Android BLE兼容,低功耗藍牙數(shù)據(jù)交互

??可以看到在執(zhí)行寫入動作成功之后,就收到了設(shè)備所回復(fù)的特征值數(shù)據(jù),然后再是收到寫入成功的日志打印。

五、源碼

如果對你有所幫助的話,不妨 StarFork,山高水長,后會有期~

源碼地址:GoodBle文章來源地址http://www.zghlxwxcb.cn/news/detail-648997.html

到了這里,關(guān)于Android Ble藍牙App(五)數(shù)據(jù)操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Android Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù)

    Android Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù)

    ??在上一篇中我們進行掃描設(shè)備的處理,本文中進行連接和發(fā)現(xiàn)服務(wù)的數(shù)據(jù)處理,運行效果圖如下所示: Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù) Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 ??現(xiàn)在我們從MainActivity進

    2024年01月16日
    瀏覽(26)
  • 低功耗藍牙(BLE)你入門了嗎

    低功耗藍牙(BLE)你入門了嗎

    ????????藍牙低功耗(Bluetooth Low Energy,或稱Bluetooth LE、BLE,舊商標(biāo)Bluetooth Smart),用于醫(yī)療保健、運動健身、安防、工業(yè)控制、家庭娛樂等領(lǐng)域。在如今的物聯(lián)網(wǎng)時代下大放異彩,扮演者重要一環(huán),是無線通信的主流技術(shù)之一(常見的無線通信技術(shù)有NFC、GPRS、Zigbee、Wi

    2024年02月02日
    瀏覽(33)
  • c# 居于Ble的藍牙通訊數(shù)據(jù)交互

    1、ble 的藍牙通訊協(xié)議UUID 2、定義一個Enum 3、定義一個ble交互類

    2024年02月15日
    瀏覽(19)
  • Android Ble藍牙App(四)UI優(yōu)化和描述符

    Android Ble藍牙App(四)UI優(yōu)化和描述符

    ??上一篇中了解了特性和屬性,同時顯示設(shè)備藍牙服務(wù)下的特性和屬性,本文中就需要來使用這些特性和屬性來完成一些功能。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù) Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 ??

    2024年02月13日
    瀏覽(16)
  • Android Ble藍牙App(六)請求MTU與顯示設(shè)備信息

    Android Ble藍牙App(六)請求MTU與顯示設(shè)備信息

    ??在上一篇文章中已經(jīng)了解了數(shù)據(jù)操作的方式,而數(shù)據(jù)交互的字節(jié)長度取決于我們手機與藍牙設(shè)備的最大支持長度。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務(wù) Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 Ble藍牙App(六)

    2024年02月04日
    瀏覽(25)
  • 微信小程序低功耗藍牙BLE快速開發(fā)js

    微信小程序低功耗藍牙BLE快速開發(fā)js

    目的: 1、為了能三分鐘快速開發(fā)BLE模塊,特此做一個筆記,按照筆記的順序開發(fā),能夠簡單、快速、規(guī)范。 2、如果以后覺得有必要改動的地方就在這里更改。 3、主要是記錄BLE連接的步驟。 https://note.youdao.com/ynoteshare/index.html?id=d662c9c1c58121ec28901d78d9aa5e80 比較完整的微信小程

    2024年02月10日
    瀏覽(109)
  • windows+python+bleak+BLE低功耗藍牙通訊連接

    windows+python+bleak+BLE低功耗藍牙通訊連接

    1.為什么選bleak ??參考這篇知乎:https://zhuanlan.zhihu.com/p/577687336 ??windows端使用python連接常規(guī)的BLE設(shè)備(藍牙4.0),僅考慮bleak模塊(排除pybluez、pybluez2、pygatt)。 2.本文主要參考 ??本文主要參考bleak的官方文檔:https://github.com/hbldh/bleak 3.本文所用設(shè)備 ??應(yīng)事先學(xué)習(xí)藍

    2024年02月02日
    瀏覽(22)
  • 深入淺出藍牙低功耗音頻BLE Audio--4-3 CIS

    深入淺出藍牙低功耗音頻BLE Audio--4-3 CIS

    ????????為了掌握核心規(guī)范中ISO新特性,先介紹單播且可連接的ISO流,即CIS,CIS的結(jié)構(gòu)框架相當(dāng)復(fù)雜,但是其建立在一些非常的原則之上。本節(jié)首先描述CIS如何被設(shè)計,解釋組成模塊如何配合工作,然后學(xué)習(xí)廣播模式的不同之處,為學(xué)習(xí)藍牙低功耗音頻方案奠定基礎(chǔ)。 ?

    2023年04月14日
    瀏覽(30)
  • 深入淺出藍牙低功耗音頻BLE Audio --4-2 ISO流和角色

    深入淺出藍牙低功耗音頻BLE Audio --4-2 ISO流和角色

    核心規(guī)范V5.2中增加ISO流特性是低功耗藍牙協(xié)議中一個全新的概念。熟悉A2DP和HFP協(xié)議的讀者都知道其拓?fù)浣Y(jié)構(gòu)局限不靈活。HFP具有雙向一對一的鏈路,典型場景是電話和耳機或免提設(shè)備之間。A2DP是一個更簡單的單播鏈路,定義Source設(shè)備產(chǎn)生音頻數(shù)據(jù),Sink設(shè)備通常是耳機,揚聲

    2023年04月11日
    瀏覽(111)
  • Qt筆記---使用Qt開發(fā)低功耗藍牙BLE(Bluetooth low energy)程序

    Qt筆記---使用Qt開發(fā)低功耗藍牙BLE(Bluetooth low energy)程序

    在Qt項目中開發(fā)BLE通信程序,即低功耗藍牙設(shè)備通信,關(guān)于藍牙設(shè)備的通信分為普通藍牙設(shè)備和低功耗藍牙設(shè)備,此文只介紹低功耗藍牙設(shè)備的連接通信方式。 開發(fā)環(huán)境: 系統(tǒng):win10 Qt:5.15.2 MSVC:2019 注:使用此版本之前使用過其他低版本的Qt和MSVC,會出現(xiàn)搜索不到設(shè)備以及

    2024年04月16日
    瀏覽(183)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包