Android BLE开发——Android手机与BLE终端通讯初识

蓝牙BLE官方Demo下载地址:   http://download.csdn.net/detail/lqw770737185/8116019
参考博客地址:    http://www.eoeandroid.com/thread-563868-1-1.html?_dsign=843d16d6html

 

     设备:MX5手机一台,农药残留检测仪一台(BLE终端设备)android

     目的:实现手机控制仪器,如发送打印指令,仪器能进行打印操做等数组

 

      关于如何打开蓝牙,配置相关权限,搜索BLE设备等步骤网上有不少资料,这里就很少作做解释了,本文主要讲通讯方面的内容。须要注意的是搜索BLE设备的结果是异步返回的,在BluetoothAdapter.LeScanCallback这个回调中返回,而且搜索过程是一个很是耗电的过程,因此咱们应该作好相应处理,例如可让它搜索10s就中止搜索等。异步

      在咱们理解Android设备与BLE终端设备通讯过程以前,咱们须要来先了解几个类:ide

      BluetoothGatt:BluetoothGatt 是咱们用的最多,也是咱们最重要的一个类,为了尽量通俗的理解,这里咱们能够把它当作Android手机与BLE终端设备创建通讯的一个管道,只有有了这个管道,咱们才有了通讯的前提。函数

      BluetoothGattService:蓝牙设备的服务,在这里咱们把BluetoothGattService比喻成班级。而Bluetoothdevice咱们把它比喻成学校,一个学校里面能够有不少班级,也就是说咱们每台BLE终端设备拥有多个服务,班级(各个服务)之间经过UUID(惟一标识符)区别。ui

      BluetoothGattCharacteristic: 蓝牙设备所拥有的特征,它是手机与BLE终端设备交换数据的关键,咱们作的全部事情,目的就是为了获得它。在这里咱们把它比喻成学生,一个班级里面有不少个学生,也就是说咱们每一个服务下拥有多个特征,学生(各个特征)之间经过UUID(惟一标识符)区别。this

      总结:当咱们想要用手机与BLE设备进行通讯时,实际上也就至关于咱们要去找一个学生交流,首先咱们须要搭建一个管道,也就是咱们须要先获取获得一个BluetoothGatt,其次咱们须要知道这个学生在哪个班级,学号是什么,这也就是咱们所说的serviceUUID,和charUUID。这里咱们还须要注意一下,找到这个学生后并非直接和他交流,他就好像一个中介同样,在手机和BLE终端设备之间帮助这二者传递着信息,咱们手机所发数据要先通过他,在由他传递到BLE设备上,而BLE设备上的返回信息,也是先传递到他那边,而后手机再从他那边进行读取。spa

      Android手机与BLE终端设备通讯结果都是以回调的形式返回,以下是几个常见的返回回调(可见于官方Demo的BluetoothLeservice类):.net

复制代码
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

        //链接状态改变的回调
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                // 链接成功后启动服务发现
                Log.e("AAAAAAAA", "启动服务发现:" + mBluetoothGatt.discoverServices());
            }
        };

        //发现服务的回调
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {                                   
                 Log.e(TAG, "成功发现服务");
                           }else{
                   Log.e(TAG, "服务发现失败,错误码为:" + status);
                        }
        };
                 
        //写操做的回调
        public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                  Log.e(TAG, "写入成功" +characteristic.getValue());
                       }
               };
          
       //读操做的回调
       public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e(TAG, "读取成功" +characteristic.getValue());
                    }
                }
                
      //数据返回的回调(此处接收BLE设备返回数据)
      public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
                };
            };
      }
复制代码

1、链接蓝牙BLE终端设备

       在咱们打开蓝牙,扫描发现想要链接的设备后,接下来要作的,固然就是去链接它了,链接方法很简单,咱们一句代码就能够实现了(以下)。能够发现,当咱们开始链接BLE终端设备的时候,链接方法就自动就帮咱们返回了一个BluetoothGatt对象了,前面咱们说到BluetoothGatt是咱们最重要的一个类,它至关于一个管道,是咱们创建通讯的前提:(这里面有三个参数,第一个参数是上下文对象,第二个参数是是否自动链接,这里设置为false,第三个参数就是上面的回调方法)

mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

链接成功与否都会经过下面这个回调来告诉咱们:

复制代码
// 链接状态改变的回调
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState) {
                        //表明链接成功,此处咱们能够发送一个广播回去告诉activity已成功链接
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                //链接成功后启动服务发现
                Log.e("AAAAAAAA", "启动服务发现:" + mBluetoothGatt.discoverServices());
            }
        }
复制代码

2、启动服务发现

 链接成功后,咱们就要去寻找咱们所须要的服务,这里须要先启动服务发现,使用一句代码便可:

mBluetoothGatt.discoverServices() ;

启动服务发现,它的结果也是经过回调函数返回:

复制代码
        // 发现服务的回调
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {      
            //成功发现服务后能够调用相应方法获得该BLE设备的全部服务,而且打印每个服务的UUID和每一个服务下各个特征的UUID
            if (status == BluetoothGatt.GATT_SUCCESS) {
                    List<BluetoothGattService> supportedGattServices =mBluetoothGatt.getServices();
                    for(int i=0;i<supportedGattServices.size();i++){
                       Log.e("AAAAA","1:BluetoothGattService UUID=:"+supportedGattServices.get(i).getUuid());
                       List<BluetoothGattCharacteristic> listGattCharacteristic=supportedGattServices.get(i).getCharacteristics();
                       for(int j=0;j<listGattCharacteristic.size();j++){
                                Log.e("a","2:   BluetoothGattCharacteristic UUID=:"+listGattCharacteristic.get(j).getUuid());
                                    }
                                 }
            } else {
                Log.e("AAAAA", "onservicesdiscovered收到: " + status);
            }
        }
复制代码

咱们也能够经过调用下面方法得知每一个特征所具备的属性:可读或者可写或者具有通知功能或者都具有等

复制代码
// 循环遍历服务以及每一个服务下面的各个特征,判断读写,通知属性
        for (BluetoothGattService gattService :supportedGattServices) {
            List<BluetoothGattCharacteristic> gattCharacteristics =supportedGattServices.getCharacteristics();
            for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                int charaProp = gattCharacteristic.getProperties();
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    // Log.e("nihao","gattCharacteristic的UUID为:"+gattCharacteristic.getUuid());
                    // Log.e("nihao","gattCharacteristic的属性为:  可读");
                }
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    // Log.e("nihao","gattCharacteristic的UUID为:"+gattCharacteristic.getUuid());
                    // Log.e("nihao","gattCharacteristic的属性为:  可写");
                }
                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    // Log.e("nihao","gattCharacteristic的UUID为:"+gattCharacteristic.getUuid()+gattCharacteristic);
                    // Log.e("nihao","gattCharacteristic的属性为:  具有通知属性");
                }

            }
        }
复制代码

3、获取Characteristic

       以前咱们说过,咱们的最终目的就是获取Characteristic来进行通讯,正常状况下,咱们能够从硬件工程师那边获得serviceUUID和characteristicUUID,也就是咱们所比喻的班级号和学号,以此来得到咱们的characteristic,但若是咱们没法得知这两个所需的UUID时,咱们也能够经过上一步的方法来获取(打印全部特征UUID,取出本身想要的特征)。此次试验我就是经过此方法得到,可是经过打印日志发现,虽然我这边的BLE终端它每一个服务下的全部特征都具备可读可写可通知属性,可是只有characteristicUUID="0000ffe1-0000-1000-8000-00805f9b34fb"这个特征UUID能进行通讯,它对应的serviceUUID="0000ffe0-0000-1000-8000-00805f9b34fb",暂且就先用这个,反正一个能用就行。假设咱们在知道serviceUUID和characteristicUUID的前提下,咱们就能够经过下面代码获取相应特征值:  

BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));
BluetoothGattCharacteristic characteristic= service.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));

4、开始通讯

       咱们在获得一个相应的特征之后,接下来就能够开始读写操做进行通讯了。

      a.读操做,读操做比较简单,只需将相应的特征值传入便可获得该特征值下的数据,以下代码:       

mBluetoothGatt.readCharacteristic(characteristic);

读取的结果经过onCharacteristicRead回调返回:(经过characteristic.getValue()就能够获得读取到的值了)

复制代码
    // 读操做的回调
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.e(TAG, "读取成功" +characteristic.getValue());
            }
        }
复制代码

       b.写操做,写操做是咱们的重点,咱们能够经过向characteristic写入指令(发送指令)以此来达到控制BLE终端设备的目的:

                           //将指令放置进特征中
                            characteristic.setValue(new byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa});
                           //设置回复形式
                           characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                           //开始写数据
                           mBluetoothGatt.writeCharacteristic(chharacteristic);

注:与仪器通讯,咱们这里发送的是16进制的数据,发送的时候须要先将其装载到byte[]数组中,例如我发送 7e 14 00 00 00 aa这个指令,我须要把它转化为ew byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa }这样去发送,由于BLE传输过程每次最大只能传输20个字节,因此若是发送的指令大于20字节的话要分包发送,例如如今要发送28个字节的,能够先write(前20个字节),开启线程sleep(几十毫秒)后在write(后面8个字节)

5、BLE终端设备返回数据
       当咱们向BLE终端设备写入指令时,若是写入成功而且指令也正确,咱们就会得到相应的响应指令,在下面这个回调中咱们能够获得BLE设备返回回来的响应指令(经过characteristic.getValue()取出返回数据):

    // 数据返回的回调(此处接收机器返回数据并做处理)
        public void onCharacteristicChanged(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic) {
            Log.e("AAAAAAAA",characteristic.getValue());
        };

接收到返回数据的前提是咱们设置了该特征具备Notification功能,因此完整的写操做代码应该是这样的(注意设置特征Notification的代码要放在最前):

复制代码
           mBluetoothGatt.setCharacteristicNotification(characteristic,true)
           //将指令放置进来
           characteristic.setValue(new byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa});
           //设置回复形式
           characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
           //开始写数据
           mBluetoothGatt.writeCharacteristic(chharacteristic);
复制代码

  以上就是本身对Android手机与BLE设备通讯一些初步认识,若是有哪里说的不正确,还请指正。

相关文章
相关标签/搜索