由于公司前段时间有一个项目要用到蓝牙BLE技术,才开始研究Ble技术,在网上也找了很多文章查看,基本的蓝牙连接通讯都有,就是出现的问题解答比较少,在这里说说个人遇到的问题。
129错误
133错误
分包发送数据
自定义数据交互格式
首次连接速度慢
蓝牙防丢器原理
Ble连接数据交互整个流程
在网上找了许多,基本都没有说明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) {// 计时过程显示 } }
'''