Android BLE简介及连接、收发数据

知识点:

经典蓝牙(Classic Bluetooth)& 低功耗蓝牙(Bluetooth Low Energy)

  • 经典蓝牙可以用与数据量比较大的传输,如语音,音乐,较高数据量传输等。

  • BLE 特点就如其名,功耗更低的同时,对数据包做出了限制。所以适用于实时性要求比较高,但是数据速率比较低的产品,如鼠标,键盘,传感设备的数据发送等。

蓝牙 4.0 支持单模和双模两种部署方式,其中单模即是我们说的 BLE,而双模指的是 Classic Bluetooth + BLE 。
实际上,BLE 和经典蓝牙的使用等各方面都像是没有关联的两个东西,甚至因为 BLE 的通讯机制不同,所以是不能向下兼容的;经典蓝牙则可以兼容到蓝牙 3.0 / 2.1。


参考 :https://www.jianshu.com/p/634b4f7154bc

(本篇文章很全,也有代码,可以参考)

开发代码:

权限:

<uses-permission android:name="android.permission.BLUETOOTH" />

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

广播接收者,用于接收蓝牙广播:

class BluetoothReceive(bleListener: BleListener) : BroadcastReceiver() {

    private val mBleListener: BleListener = bleListener

    override fun onReceive(context: Context?, intent: Intent) {
        val action = intent.action
        if (action == BluetoothDevice.ACTION_FOUND) {
            val device =
                intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
            val ssi = intent.extras!!.getShort(BluetoothDevice.EXTRA_RSSI)
            val deviceClass = device!!.bluetoothClass.majorDeviceClass
            mBleListener.onBleScanListener(device, deviceClass, ssi)
        } else if (action == BluetoothAdapter.ACTION_DISCOVERY_FINISHED) {
            mBleListener.onScanFinish()
        }
    }
}

回调:

interface BleListener {

    /**
     * BLE设备回调
     * @param bluetoothDevice 蓝牙设备
     * @param type 蓝牙类别(手机等)
     * @param ssr 蓝牙信号强度
     */
    fun onBleScanListener(bluetoothDevice: BluetoothDevice, type: Int, ssr: Short)

    /**
     * 搜索完成
     */
    fun onScanFinish()
}

核心类就是:BluetoothDevice,蓝牙所有的信息都是从这里面取

Activity注册一下:

// 广播注册
mBluetoothReceive = BluetoothReceive(this)
var intentFilter = IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
mContext.registerReceiver(mBluetoothReceive, intentFilter)
intentFilter = IntentFilter(BluetoothDevice.ACTION_FOUND)
mContext.registerReceiver(mBluetoothReceive, intentFilter)

mAdapter = BluetoothAdapter.getDefaultAdapter()

核心方法:

    /**
     * 打开蓝牙
     */
    override fun startBle() {
        if (!mAdapter.isEnabled) mAdapter.enable()
    }

    /**
     * 扫描蓝牙设备
     */
    override fun scanBleDevice() {
        if (!mAdapter.isEnabled) mAdapter.enable()
        if (mAdapter.isDiscovering) {
            mAdapter.cancelDiscovery()
            mAdapter.startDiscovery()
        } else {
//            SystemClock.sleep(1000)
            mAdapter.startDiscovery()
        }
        mBleList.clear()
    }

    /**
     * 停止扫描
     */
    override fun stopScanBleDevice() {
        if (mAdapter.isDiscovering) mAdapter.cancelDiscovery()
    }

    /**
     * 连接
     */
    override fun connect(bleBean: BleBean) {
        // 获取蓝牙设备
        val ble = mBleDevices[bleBean.address]
        // 直接连接
        mGatt = ble?.connectGatt(mContext, false, mBluetoothGattCallback)!!
    }

    /**
     * 断开当前连接
     */
    override fun disConnect() {
        mGatt.disconnect()
    }

    /**
     * 释放资源
     */
    override fun onDestroy() {
        mBleList.clear()
        mBleUiImplList.clear()
        // 注销广播接收者
        this.mContext.unregisterReceiver(mBluetoothReceive)
    }

以上是基本调用及连接,下面是读写数据的回调。

    // BLE的回调
    private val mBluetoothGattCallback = object : BluetoothGattCallback() {
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                // 开始搜索服务
                gatt?.discoverServices()
            }
            // 接受到设备断开的状态后,还要手动调用 close(),否则可能出现连接未断开导致的重连失败等问题;
            if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                gatt?.close()
                // 回调连接状态
                for (bleUiImpl in mBleUiImplList) bleUiImpl.onDisConnect()
            }
            if (newState == BluetoothProfile.STATE_CONNECTING) {
                // 设备在连接中
            }
        }

        // 成功发现服务的回调
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)

            if (gatt == null) {
                return
            }
            if (status == BluetoothGatt.GATT_SUCCESS) { // 发现蓝牙服务成功
                val gattServicesList =
                    gatt.services
                for (i in gattServicesList.indices) {
                    if (gattServicesList[i].uuid == UUID.fromString(SERVICES_UUID)) { // 如果servicesUUID相同,则做如下处理
                        // 设置写入特征UUID
                        mWriteCharacteristic =
                            gattServicesList[i].getCharacteristic(UUID.fromString(WRITE_UUID))
                        // 设置监听特征UUID
                        val notifyCharacteristic =
                            gattServicesList[i].getCharacteristic(UUID.fromString(NOTIFY_UUID))
                        // 开启监听
                        gatt.setCharacteristicNotification(notifyCharacteristic, true)
                        gatt.setCharacteristicNotification(mWriteCharacteristic, true)
                        break
                    }
                }
            }
            for (bleUiImpl in mBleUiImplList) bleUiImpl.onServicesDiscovered(status)
        }

        /**
         * 接收到数据
         */
        override fun onCharacteristicRead(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
//            if (status == BluetoothGatt.GATT_SUCCESS) {
//                Log.d("123", "收到到数据:")
//            }
            for (bleUiImpl in mBleUiImplList) bleUiImpl.onServicesDiscovered(status)
            super.onCharacteristicRead(gatt, characteristic, status)
        }

        /**
         * 写入数据 调用 writeCharacteristic 的回调
         */
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)

            val stringBuilder = StringBuilder()
            characteristic?.value
                ?.filter { it > 0 }
                ?.forEach { stringBuilder.append(String.format("%c", it)) }

            if (characteristic != null)
                ToastUtils.showToast("成功发送:".plus(stringBuilder.toString()))
        }


        // 调用 writeDescriptor 的回调
        override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorWrite(gatt, descriptor, status)
        }

        /**
         * 硬件返回数据
         */
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicChanged(gatt, characteristic)

            val stringBuilder = StringBuilder()
            if (characteristic != null) {
                characteristic.value?.forEach {
                    val b = it
//                hexStringBuilder.append(Integer.toHexString(b.toInt()))
                    stringBuilder.append(String.format("%c", b))
                }
            }
            for (bleUiImpl in mBleUiImplList) bleUiImpl.onReceive(
                null != characteristic,
                stringBuilder.toString()
            )
        }
    }

上述回调部分,可以写你的业务逻辑,这里不贴代码了。。。

以上代码粘贴后改成自己的即可,只是基本的使用。

要注意的点:

1.断开最好调用close,否则下次连接会失败(报133)。当然失败再次连接就好。

2.只能连接BLE设备,连接传统蓝牙设备拿不到回调。

3.如果搜不到BLE设备的话,重启下BLE设备。

传统蓝牙可以参考下面文章:

https://blog.csdn.net/huangliniqng/article/details/82187966

写在最后:

BLE直连、自动连接这种的,可以在以上基础用MAC(特定设备)或者NAME(某类产品)连。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在 Android 平台上使用 Bluetooth Low Energy(BLE)API 进行收发数据的示例代码: 首先,您需要在应用程序中获取 BluetoothAdapter 和 BluetoothGatt 对象。然后,您需要扫描并连接BLE 设备,获取其 BluetoothGatt 对象。一旦连接成功,您可以使用 BluetoothGatt 对象进行数据传输。 发送数据: ```java // 获取要发送的数据 byte[] data = "hello world".getBytes(); // 获取要发送数据的特征值对象 BluetoothGattCharacteristic characteristic = bluetoothGatt.getService(serviceUuid) .getCharacteristic(characteristicUuid); // 设置数据到特征值中 characteristic.setValue(data); // 发送数据 bluetoothGatt.writeCharacteristic(characteristic); ``` 在上面的示例代码中,`serviceUuid` 和 `characteristicUuid` 是您要发送数据的特征值的 UUID。 一旦您调用 `writeCharacteristic` 方法,BLE 设备将接收到发送的数据。如果发送成功,将会触发 `onCharacteristicWrite` 回调。 接收数据: 要接收 BLE 设备发送的数据,您需要在 BluetoothGatt 对象上注册接收数据的回调。 ```java // 注册接收数据的回调 bluetoothGatt.setCharacteristicNotification(characteristic, true); // 获取数据的描述符 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descriptorUuid); // 启用数据的通知 descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetoothGatt.writeDescriptor(descriptor); ``` 在上面的示例代码中,`characteristic` 是您要接收数据的特征值对象,`descriptorUuid` 是通知数据的描述符的 UUID。 一旦您调用 `setCharacteristicNotification` 和 `writeDescriptor` 方法,BLE 设备将开始将数据发送到 Android 设备。当数据到达时,将触发 `onCharacteristicChanged` 回调。在此回调中,您可以从特征值对象中获取数据并进行处理。 ```java @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // 处理接收到的数据 byte[] data = characteristic.getValue(); // ... } ``` 请注意,BLE 通信是异步的,因此您需要在适当的回调中处理数据。如果您需要连续接收多个特征值的数据,请考虑使用 BluetoothGatt 的 `setCharacteristicNotification` 方法注册通知,以便连续接收数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值