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回调得到的蓝牙RSSIprivate 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();
    }

    // 获取已经得到的RSSIpublic 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) {// 计时过程显示
        }
    }

未完待续….

你可能感兴趣的:(android,蓝牙,通讯)