Android 蓝牙4.0 Ble通讯问题小汇总

Android 蓝牙4.0 Ble通讯问题小汇总

由于公司前段时间有一个项目要用到蓝牙BLE技术,才开始研究Ble技术,在网上也找了很多文章查看,基本的蓝牙连接通讯都有,就是出现的问题解答比较少,在这里说说个人遇到的问题。

  • 129错误
  • 133错误
  • 分包发送数据
  • 自定义数据交互格式
  • 首次连接速度慢
  • 蓝牙防丢器原理
  • Ble连接数据交互整个流程

129错误

在网上找了许多,基本都没有说明129错误在BLE中代表什么。个人测试后,猜测129类似于连接蓝牙,获取服务超时的返回值,一般存在于蓝牙信号比较弱或者蓝牙附近存在电池,变压器等设备影响到蓝牙信号时

代码块

//连接蓝牙成功后,获取服务
mBluetoothGatt.discoverServices()

// 发现新服务
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            try {
                if (status == BluetoothGatt.GATT_SUCCESS
                        && mOnServiceDiscoverListener != null) {
                    mOnServiceDiscoverListener.onServiceDiscover(gatt);
                } else {
                    LogUtil.i(TAG, System.currentTimeMillis() + "发现新服务端失败"
                            + status);
                    close();
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

133错误

跟129错误类似,表示获取服务失败的返回值

代码块

//连接蓝牙成功后,获取服务
mBluetoothGatt.discoverServices()

// 发现新服务
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            try {
                if (status == BluetoothGatt.GATT_SUCCESS
                        && mOnServiceDiscoverListener != null) {
                    mOnServiceDiscoverListener.onServiceDiscover(gatt);
                } else {
                    LogUtil.i(TAG, System.currentTimeMillis() + "发现新服务端失败"
                            + status);
                    close();
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

分包发送数据

蓝牙BLE支持的数据发送每包只能20字节,所以想要发送比较大的数据包只能通过分包发送。注意:如果你在要发送数据的地方直接一个for循环把所有分包的数据发完,蓝牙设备那边也只会收到一包数据而已,再此有两种方法解决: 
1、在for循环中每发一包数据加一个20毫秒的休眠时间,缺点:时间不可控,容易导致丢包。 
2、每发完一包数据,成功发送后系统会进入onCharacteristicWrite回调里面,在这里进行发送第二包和第二包之后的数据(代码如下)。

代码块

// 发送大于20字节的包(第一包数据)
    public void sendPackFromOut20(BluetoothGatt gatt) {
        sendLength = con.length;
        sendtabLength = 20;
        byte[] c = new byte[20];
        for (int i = 0; i < 20; i++) {
            c[i] = con[i];
        }
        BluetoothGattService RxService = gatt.getService(UUID
                .fromString(BluetoothLeClass.UUID_KEY_Data));
        BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(UUID
                .fromString(BluetoothLeClass.UUID_KEY_Write));
        TxChar.setValue(c);
        mBLE.writeCharacteristic(TxChar);
    }

    //超过第一包的数据在上一包数据发送成功后系统回调里面发
    /**
      * 写入BLE终端数据成功回调
      */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic) {
            try {
                LogUtil.i(TAG, new String(characteristic.getValue()));

                    int s = sendLength - sendtabLength;
                    if (s > 0) {
                        // 发送con未发送完的数据
                        byte[] c;
                        if (s > 20) {
                            c = new byte[20];
                            for (int i = 0; i < 20; i++) {
                                c[i] = con[i + sendtabLength];
                            }
                            sendtabLength += 20;
                        } else {
                            c = new byte[s];
                            for (int i = 0; i < s; i++) {
                                c[i] = con[i + sendtabLength];
                            }
                            sendtabLength += s;
                        }
                        BluetoothGattService RxService = gatt.getService(UUID
                                .fromString(BluetoothLeClass.UUID_KEY_Data));
                        BluetoothGattCharacteristic TxChar = RxService
                                .getCharacteristic(UUID
                                        .fromString(BluetoothLeClass.UUID_KEY_Write));
                        TxChar.setValue(c);
                        mBLE.writeCharacteristic(TxChar);
                    } else {
                        sendLength = -1;
                        sendtabLength = -1;
                        LogUtil.i(TAG, "所有包已发完!");
                    }

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

自定义数据交互格式

这个类似于android跟http数据交互的格式,无非就是定义一些样式让android和蓝牙模块两边都能识别,为了安全起见可以对数据进行加密处理。由于我这边是跟蓝牙单片机进行交互的,蓝牙单片机不支持String,只能通过byte[]数组按位去组装数据交互。(结构如下) 
数据格式:[起始码][长度码] [命令码] [数据码] [校验码] 
起始码 :固定为 0XAA 
长度码 :命令码+数据码+校验码 
命令码,数据码(自定义数据接口) 
校验码 :一个字节,前面所有数据值相加之和 
加密:self加密和DES加密对整个数据码进行加密


首次连接速度慢

由于蓝牙首次连接要配置缓冲所有广播的服务,所以一般第一次连接都比较慢,如果想要加快第一次连接速度,只能让蓝牙模块关闭部分不必要的广播。


蓝牙防丢器原理

蓝牙防丢器的原理其实很简单,就是通过手机app定时去扫描你配置好的蓝牙单片机,如果扫描到该蓝牙单片机返回的rssi值(蓝牙的信号值)超出app设定的值,则app将会报警;或者扫不到该单片机app也会报警。(代码如下)

代码块

// 初始化蓝牙
private void initBLE() {
        // TODO Auto-generated method stub
            // 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
            if (!mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(mContext, "手机不支持ble蓝牙", Toast.LENGTH_SHORT)
                        .show();
            }

            // 初始化 Bluetooth adapter,
            // 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
            final BluetoothManager bluetoothManager = (BluetoothManager) mContext
                    .getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();

            // 检查设备上是否支持蓝牙
            if (mBluetoothAdapter == null) {
                Toast.makeText(mContext, "手机不支持蓝牙", Toast.LENGTH_SHORT).show();
                return;
            }

            // 打开蓝牙
            if (!mBluetoothAdapter.isEnabled()) {
                mBluetoothAdapter.enable();
            }

            // 开始扫描
            if (dAddress.size() > 0) {
                dAddress.clear();
            }
            if (rssiDistance.size() > 0) {
                rssiDistance.clear();
            }
            if (!mScanning) {
                mScanning = true;
                scanLeDevice(true);
            }
    }

// 扫描
private void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);

                }
            }, SCAN_PERIOD);

            mScanning = true;
            boolean scan = mBluetoothAdapter.startLeScan(mLeScanCallback);

        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

// 设备扫描
    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, int rssi,
                byte[] scanRecord) {
            LogUtil.i(
                    TAG,
                    device.getAddress() + ","
                            + (int) BLEUtil.RssiToDistance(rssi));
            if (!dAddress.contains(device.getAddress())) {
            //对比获取到的设备的mac地址和rssi值进行处理
                dAddress.add(device.getAddress());
                rssiDistance.put(device.getAddress(),
                        (int) BLEUtil.RssiToDistance(rssi));
            }
        }
    };

Ble连接数据交互整个流程

蓝牙Ble连接跟蓝牙防丢器的原理其实是一样的,先启动蓝牙,然后扫面附近的蓝牙(只有android5.0+的手机的蓝牙才会被扫描到,或支持ble的蓝牙单片机),拿到所有扫描的蓝牙进行筛选匹配到你想要连接的蓝牙,然后连接。(代码如下)

代码块

// 初始化蓝牙
private void initBLE() {
        // TODO Auto-generated method stub
            // 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
            if (!mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(mContext, "手机不支持ble蓝牙", Toast.LENGTH_SHORT)
                        .show();
            }

            // 初始化 Bluetooth adapter,
            // 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
            final BluetoothManager bluetoothManager = (BluetoothManager) mContext
                    .getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();

            // 检查设备上是否支持蓝牙
            if (mBluetoothAdapter == null) {
                Toast.makeText(mContext, "手机不支持蓝牙", Toast.LENGTH_SHORT).show();
                return;
            }

            // 打开蓝牙
            if (!mBluetoothAdapter.isEnabled()) {
                mBluetoothAdapter.enable();
            }

            // 开始扫描
            if (dAddress.size() > 0) {
                dAddress.clear();
            }
            if (rssiDistance.size() > 0) {
                rssiDistance.clear();
            }
            if (!mScanning) {
                mScanning = true;
                scanLeDevice(true);
            }
    }

// 扫描
private void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    // 开始连接,筛选后的蓝牙的mac地址
                    mBLE.connect(mac)
                }
            }, SCAN_PERIOD);

            mScanning = true;
            boolean scan = mBluetoothAdapter.startLeScan(mLeScanCallback);

        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

// 设备扫描
    private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, int rssi,
                byte[] scanRecord) {
            LogUtil.i(
                    TAG,
                    device.getAddress() + ","
                            + (int) BLEUtil.RssiToDistance(rssi));
            if (!dAddress.contains(device.getAddress())) {
            //对比获取到的设备的mac地址和rssi值进行处理
                dAddress.add(device.getAddress());
                rssiDistance.put(device.getAddress(),
                        (int) BLEUtil.RssiToDistance(rssi));
            }
        }
    };

附上封装好的BluetoothLeClass,主要封装好:连接,收发数据的回调,断开蓝牙。调用mBLE.connect(mac)连接蓝牙后进入public boolean connect(final String address) {}方法,根据你是否是二次连接进行处理,如果是首次连接将创建mGattCallback ,方法private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {}里面封装了蓝牙状态改变(连接/断开)回调onConnectionStateChange;连接成功后调mBluetoothGatt.discoverServices()获取收发数据的服务,在onServicesDiscovered中获取到服务,我这边在前台mOnServiceDiscoverListener.onServiceDiscover(gatt);回调中进行数据收发(代码如下)

代码块

package com.etclients.util;

import java.util.List;
import java.util.UUID;

import com.etclients.activity.MainActivity;
import com.etclients.receiver.AlarmRecevier;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

/**
 * Service for managing connection and data communication with a GATT server
 * hosted on a given Bluetooth LE device.
 */
public class BluetoothLeClass { private final static String TAG = BluetoothLeClass.class.getSimpleName(); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; // BLE回调得到的蓝牙RSSI值 private static int BLERSSI = 0; public final static String UUID_KEY_Write = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";// 手机发送数据给设备 public final static String UUID_KEY_Read = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";// 设备发送数据给手机 public final static String UUID_KEY_Data = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";// public static final UUID CCCD = UUID .fromString("00002902-0000-1000-8000-00805f9b34fb"); private byte[] c; private boolean is = false; public interface OnConnectListener { public void onConnect(BluetoothGatt gatt); } public interface OnDisconnectListener { public void onDisconnect(BluetoothGatt gatt); } public interface OnServiceDiscoverListener { public void onServiceDiscover(BluetoothGatt gatt); } public interface OnDataAvailableListener { public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status); public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor); } private OnConnectListener mOnConnectListener; private OnDisconnectListener mOnDisconnectListener; private OnServiceDiscoverListener mOnServiceDiscoverListener; private OnDataAvailableListener mOnDataAvailableListener; private Context mContext; public void setOnConnectListener(OnConnectListener l) { mOnConnectListener = l; } public void setOnDisconnectListener(OnDisconnectListener l) { mOnDisconnectListener = l; } public void setOnServiceDiscoverListener(OnServiceDiscoverListener l) { mOnServiceDiscoverListener = l; } public void setOnDataAvailableListener(OnDataAvailableListener l) { mOnDataAvailableListener = l; } public BluetoothLeClass(Context c) { mContext = c; } // Implements callback methods for GATT events that the app cares about. For // example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // 当蓝牙设备已经连接 if (newState == BluetoothProfile.STATE_CONNECTED) { if (mOnConnectListener != null) mOnConnectListener.onConnect(gatt); LogUtil.i(TAG, "已连接 to GATT server." + System.currentTimeMillis()); // 成功连接后发现服务的尝试。 try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } LogUtil.i(TAG, System.currentTimeMillis() / 1000 + "发现服务的尝试" + mBluetoothGatt.discoverServices()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { try { // 当设备无法连接 if (mOnDisconnectListener != null) mOnDisconnectListener.onDisconnect(gatt); LogUtil.i(TAG, "断开 GATT server."); close2(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); close(); } } } // 发现新服务 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { try { if (status == BluetoothGatt.GATT_SUCCESS && mOnServiceDiscoverListener != null) { mOnServiceDiscoverListener.onServiceDiscover(gatt); } else { LogUtil.i(TAG, System.currentTimeMillis() + "发现新服务端失败" + status); close(); Intent intent = new Intent(); intent.setAction(MainActivity.ACTION_UPDATEUI); Bundle bundle = new Bundle(); bundle.putString("msg", "发现服务129失败,请重新开门!"); intent.putExtras(bundle); mContext.sendBroadcast(intent); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // 读取特征值 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { LogUtil.i(TAG, "onCharacteristicRead"); if (mOnDataAvailableListener != null) mOnDataAvailableListener.onCharacteristicRead(gatt, characteristic, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { LogUtil.i(TAG, "onCharacteristicChanged"); if (mOnDataAvailableListener != null) mOnDataAvailableListener.onCharacteristicChanged(gatt, characteristic); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { // TODO Auto-generated method stub super.onCharacteristicWrite(gatt, characteristic, status); LogUtil.i(TAG, "onCharacteristicWrite"); if (status == BluetoothGatt.GATT_SUCCESS && mOnDataAvailableListener != null) mOnDataAvailableListener.onCharacteristicWrite(gatt, characteristic); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { // TODO Auto-generated method stub super.onDescriptorWrite(gatt, descriptor, status); if (status == BluetoothGatt.GATT_SUCCESS && mOnDataAvailableListener != null) { mOnDataAvailableListener.onDescriptorWrite(gatt, descriptor); LogUtil.i(TAG, "onDescriptorWrite"); } else { // 重新连接 if (mBluetoothGatt != null) { // disconnect(); close(); } System.out .println("onDescriptorWrite重新连接mBluetoothGatt== null"); mBluetoothGatt = mBluetoothAdapter.getRemoteDevice( AlarmRecevier.mac).connectGatt(mContext, false, mGattCallback); mBluetoothDeviceAddress = AlarmRecevier.mac; } } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { // TODO Auto-generated method stub super.onReadRemoteRssi(gatt, rssi, status); // 将回调的RSSI值赋值 BLERSSI = rssi; LogUtil.i(TAG, "rssi = " + rssi); } }; /** * Initializes a reference to the local Bluetooth adapter. * * @return Return true if the initialization is successful. */ public boolean initialize() { // For API level 18 and above, get a reference to BluetoothAdapter // through // BluetoothManager. if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) mContext .getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } return true; } /** * 开始连接蓝牙 * * @param address * The device address of the destination device. * * @return Return true if the connection is initiated successfully. The * connection result is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public boolean connect(final String address) { if (mBluetoothAdapter == null || address == null) { LogUtil.i(TAG, "你没有初始化或未指定的地址。"); return false; } // Previously connected device. Try to reconnect. if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { LogUtil.i(TAG, "mBluetoothGatt连接已存在"); close(); } final BluetoothDevice device = mBluetoothAdapter .getRemoteDevice(address); if (device == null) { return false; } //创建一个BluetoothGattCallback(蓝牙连接状态,收发数据的回调) mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback); LogUtil.i(TAG, "试图创建一个新的连接。"); mBluetoothDeviceAddress = address; return true; } /** * Disconnects an existing connection or cancel a pending connection. The * disconnection result is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return; } mBluetoothGatt.disconnect(); try { Thread.sleep(20); close(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * After using a given BLE device, the app must call this method to ensure * resources are released properly. */ public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; LogUtil.i(TAG, "释放资源!"); } public void close2() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; try { DialogUtil.dismissAnimationDialog(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } LogUtil.i(TAG, "释放资源,关闭加载动画!"); } /** * Request a read on a given {@code BluetoothGattCharacteristic}. The read * result is reported asynchronously through the * {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} * callback. * * @param characteristic * The characteristic to read from. */ public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } boolean is = mBluetoothGatt.readCharacteristic(characteristic); LogUtil.i(TAG, "开始回调!" + is); } /** * Enables or disables notification on a give characteristic. * * @param characteristic * Characteristic to act on. * @param enabled * If true, enable notification. False otherwise. */ public void setCharacteristicNotification( BluetoothGattCharacteristic characteristic, boolean enabled) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { LogUtil.i(TAG, "BluetoothAdapter not initialized"); return; } try { LogUtil.i(TAG, characteristic + "," + enabled); boolean is = mBluetoothGatt.setCharacteristicNotification( characteristic, enabled); LogUtil.i(TAG, "setCharacteristicNotification = " + is); BluetoothGattDescriptor descriptor = characteristic .getDescriptor(CCCD); descriptor .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void writeCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothGatt != null) { boolean is = mBluetoothGatt.writeCharacteristic(characteristic); LogUtil.i(TAG, "writeCharacteristic = " + is); } } /** * Retrieves a list of supported GATT services on the connected device. This * should be invoked only after {@code BluetoothGatt#discoverServices()} * completes successfully. * * @return A {@code List} of supported services. */ public List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices(); } // 获取已经得到的RSSI值 public static int getBLERSSI() { return BLERSSI; } // 是都能读取到已连接设备的RSSI值 // 执行该方法一次,获得蓝牙回调onReadRemoteRssi()一次 /** * Read the RSSI for a connected remote device. * */ public boolean getRssiVal() { if (mBluetoothGatt == null) return false; return mBluetoothGatt.readRemoteRssi(); } }

前台private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener() {}中通过获取的服务绑定数据改变后发送通知 mBLE.setCharacteristicNotification(RxChar, true);然后在调mBluetoothGatt.writeDescriptor(descriptor);在onDescriptorWrite(连接首次发送数据)回调中开始向BLE终端写入数据,蓝牙单片机收到数据后向手机返回数据,数据从onCharacteristicChanged方法回调到前端,前端收到数据后进行二次发送数据,具体数据发送流程见代码 (代码如下)

代码块

/**
     * 搜索到BLE终端服务的事件
     */
    private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener() {

        @Override
        public void onServiceDiscover(BluetoothGatt gatt) {
            if (gatt != null) {
                // 设置UUID_KEY_Read字服务数据改变监听
                try {
                    LogUtil.i(TAG, System.currentTimeMillis() / 1000
                            + "onServiceDiscover");
                    BluetoothGattService RxService = gatt.getService(UUID
                            .fromString(BluetoothLeClass.UUID_KEY_Data));
                    if (RxService != null) {
                        BluetoothGattCharacteristic RxChar = RxService
                                .getCharacteristic(UUID
                                        .fromString(BluetoothLeClass.UUID_KEY_Read));
                        if (RxChar != null) {
                            //绑定数据改变后发送通知
                            mBLE.setCharacteristicNotification(RxChar, true);
                        } else {
                            //获取服务失败,关闭蓝牙
                            mBLE.close();                                   
                        }
                    } else {
                        //获取服务失败,关闭蓝牙
                        mBLE.close();                       
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    };

    /**
     * 收到BLE终端数据交互的事件
     */
    private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener() {

        /**
         * 读取BLE终端数据回调
         */
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS)
                LogUtil.i(TAG, "读取BLE终端数据回调");
        }

        /**
         * BLE终端数据改变通知回调
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic) {
            byte[] value = characteristic.getValue();
            LogUtil.i(TAG, "BLE终端数据改变通知回调" + new String(value));
            //在这里接受蓝牙单片机的数据
            //进行处理后
            //发送二次数据
            byte[] content = BLEParams.sendReturnCode(commandcode);//封装好的数据
            BluetoothGattService RxService = gatt.getService(UUID
                    .fromString(BluetoothLeClass.UUID_KEY_Data));
            BluetoothGattCharacteristic TxChar = RxService
                    .getCharacteristic(UUID
                            .fromString(BluetoothLeClass.UUID_KEY_Write));
            TxChar.setValue(content);
            mBLE.writeCharacteristic(TxChar);           
        }

        /**
         * 写入BLE终端数据成功回调
         */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic) {
            //二次发送数据成功后在此返回发送的数据
                LogUtil.i(TAG, new String(characteristic.getValue()));
            //可以在此进行分包发送数据

        }

        /**
         * 写入BLE终端通知数据成功回调
         */
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt,
                BluetoothGattDescriptor descriptor) {
            // TODO Auto-generated method stub
            // 开始向BLE终端写入数据(连接首次发送数据)           
                // 查询版本号
                sendGetConnectId(0x01, gatt);

        }

    };

    // 倒数
    /* 定义一个倒计时的内部类 */
    class TimeCount extends CountDownTimer { public TimeCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval);// 参数依次为总时长,和计时的时间间隔 } @Override public void onFinish() {// 计时完毕时触发 if (isTimeout) { // 超时 mBLE.close(); } } @Override public void onTick(long millisUntilFinished) {// 计时过程显示 } }

转自:http://www.voidcn.com/article/p-ndpnnooa-bpr.html

猜你喜欢

转载自blog.csdn.net/sam_zhang1984/article/details/86574010
今日推荐