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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容