安卓ble蓝牙快速开发

1、首先说一下BLE设备有什么东西

一个BLE终端可以包含多个Service(服务)

一个Service可以包含多个Characteristic(特征)

一个Characteristic包含一个value和多个Descriptor(描述符),一个Descriptor包含一个Value。

其中,我们要注意的是,每一个Service、Characteristic都会有一个uuid,这是一个唯一值,我们接下来的传输数据,将用到这个。每一个Characteristic都有一个Value,我们就是通过改变这个值,来对设备进行交互的。ble开发主要就是找到指定的Service,Characteristic,然后通过写的Characteristic些数据,通过通知的Characteristic读返回的数据,通过
读的Characteristic读取某些值。

这些东西一般蓝牙文档中就会给出来这里写图片描述

当然如果没有文档可下载nrf master control panel 这个app根据协议文档进行测试,找出设备使用的Service和Characteristic。

2.在android中,对ble设备的操作实际上是对BluetoothGatt的操作,所以我们首先要想办法获取到BluetoothGatt。对蓝牙设备的连接过程也就是获取BluetoothGatt的获取过程,大概有以下几步:

1.添加权限(你也知道啦,想要连接ble设备,肯定得获取手机相关的权限使用权啦)

 <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission      android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

2.扫描Ble设备:

想要扫描设备,首先我们先要拿到BluetoothManager,通过BluetoothManager的getAdapter()方法再拿到BluetoothAdapter,然后再通过BluetoothAdapter的startSacn( LeScanCallback)的方法开始扫描设备。值得注意的是,我们还需要实现LeScanCallback的回调方法。(这里可通过蓝牙名称或者蓝牙mac地址找到蓝牙设备)

private BluetoothAdapter.LeScanCallback mLeScanCallback = new  BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            ULog.d(TAG,"onscan");
            //  BluetoothDevice  name=eBody-Scale address=BC:6A:29:26:97:5E
            ULog.d(TAG,"BluetoothDevice  name=" + device.getName() + " address=" + device.getAddress());
            //  BluetoothDevice  name=eBody-Scale address=BC:6A:29:26:97:5E
            //根据蓝牙名称或者mac地址找到对应的蓝牙设备
            if (isScanByName){
                if (name.equals(device.getName())) {
                    ULog.d(TAG,"find_device_by_name");
                    mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
                    if (mScanning) {
                        scanLeDevice(false);
                    }

                }
            }else {
                if (mac.equals(device.getAddress())) {
                    ULog.d(TAG,"find_device_by_mac");
                    mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
                    if (mScanning) {
                        scanLeDevice(false);
                    }

                }
            }

在其回调方法中会有这么一个函数,onLeScan(BluetoothDevice, rssi, byte[])。当中的bluetoothDevice就是我们扫描的设备;rssi是int类型,代表设备的信号强度,是负的,数值越大代表信号强度越大;byte[]这个byte数组就是设备广播的相关数据(在我们项目中,我们是依靠这个广播来判断我们设备时候在充电状态的,各个设备应该都有自己的商定)。

3.建立连接:

当扫描到我们所需的设备,就可以开始建立连接了。主要是使用上面所扫描到设备的BluetoothDevice.connectGatt(context, boolean, BluetoothGattCallback)的方法进行连接,这个函数将返回BluetoothGatt的实例,到此,我们就拿到了BluetoothGatt了,就可以进行相关读写数据操作了。(连接之后关闭蓝牙扫描,蓝牙扫描很耗电和占用系统资源)

BluetoothGattCallback抽象类,只有9个方法,字面意思就都可以看懂,在处理连接事件上,需要处理方法:
比如连接状态:

   //连接成功判断
            if (newState == BluetoothProfile.STATE_CONNECTED) {

                ULog.d(TAG,"connected");
                btMsgCallBack.onConnected();
                mBluetoothGatt.discoverServices();
                // 连接断开判断
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                ULog.d(TAG,"onDisConnected");
                btMsgCallBack.onDisConnected();
                gatt.close();

                //连接断开延时一秒后继续扫秒蓝牙连接
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (isScan)
                scanLeDevice(true);


            } else if (status != BluetoothGatt.GATT_SUCCESS) { // 连接失败判断
                ULog.d(TAG,"onConnectFail");
                btMsgCallBack.onConnectFail();

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (isScan)
                    scanLeDevice(true);
            }

其他几个回调就不说了,项目中有注释,大致可以去看下。。。

3.蓝牙连接成功后就可以找出我们指定的服务和通知的特征,写的特征,读的特征。
//通知特征设置激活(有些设备特征值有很多个,要一个一个去激活)

  BluetoothGattCharacteristic characteristic = btService.getCharacteristic(UUID.fromString(notifyUUid[0]));
                if (characteristic != null) {
                    mBluetoothGatt.setCharacteristicNotification(characteristic, true);
                    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(BleConfig.CLIENT_CHARACTERISTIC_CONFIG));
                    if (descriptor != null) {
                        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                        mBluetoothGatt.writeDescriptor(descriptor);
                    }
                  //  mBluetoothGatt.readCharacteristic(characteristic);
                }

成功后,蓝牙设备如果有数据就会回调onCharacteristicChanged(),
我们这里接受处理数据即可(有的蓝牙设备还需要发送一条命令给他成功后才会返回数据)

   /**
         * 返回数据。
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            // 数据
            ULog.d(TAG,"onCharacteristicChanged");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < characteristic.getValue().length; i++) {
              //  sb.append (characteristic.getValue()[i] & 0xff).append(" ") ;   //变成int字符串数据,方便处理
               //这里也可变为16进制数据,方便对协议
                sb.append (String.format("%02X ",characteristic.getValue()[i] & 0xff)).append(" ") ;
            }

            btMsgCallBack.onReceiveMessage(sb.toString());

        }

4.由于项目中经常用到,所以自己封装了一个,调用起来非常方便,代码已上传github.

//蓝牙辅助类初始化

 btMsgListener = BlueToothMessageListener.create(this).setCallback(btMsgCallBack)
                .setServiceUUid(DEVICE_SERVICE_UUID) //必须要
                .setNotifyUUid(NOTIFY_CHARACTERISTICSUUID)//必须要
                .setReadUUid(READ_CHARACTERISTICSUUID)
                .setWriteUUid(WRITE_CHARACTERISTICSUUID)
                .setBleName(DEVICE_NAME_SPO2) //蓝牙名称和mac地址二选一
                .setBleMac(DEVICE_MAC_SPO2);

github项目地址[bleUtils](https://github.com/tangchao5206/BleUtils
本人水平有限,如果觉得还行,记得点赞

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值