本文是Android作为ble server端,启动APP后直接启动server,等待client来连接。
废话不多说,直接上代码:
APP启动后调用初始化:
BleServerInstance.getInstance().open()
退出APP的时候:
override fun onDestroy() {
super.onDestroy()
BleServerInstance.getInstance().closeBle()
}
BleServerInstance.java
public class BleServerInstance {
private static int HEAD1 = 0x3A;
private static int HEAD2 = 0xA3;
private static int HEAD_5B = 0x5B;
private static int HEAD_B3 = 0xB3;
private static int CMD_01 = 0x01;
private static int CMD_02 = 0x02;
private List<Byte> mBytes = new ArrayList<>();
private UUID UUID_SERVER = UUID.fromString("000000ff-0000-1000-8000-00805f9b34fb");
private UUID UUID_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
private UUID UUID_CHARWRITE = UUID.fromString("0000ff01-0000-1000-8000-00805f9b34fb");
private static String BLE_NAME = "BLE_NAME";
private BlePeripheralUtils blePeripheralUtils;
private BlePeripheralCallback callback = new BlePeripheralCallback() {
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
LiveDataBus.get().with(LiveDataConstants.BLE_CONNECT_STATES).postValue(newState);
if (newState == 2){
blePeripheralUtils.stopBluetoothLeAdvertiser();
}
}
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
String ble = ByteUtil.hexBytesToString(requestBytes).trim();
Log.i("lala", "======onCharacteristicChanged==========>" + ble);
receiveData(requestBytes);
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
// blePeripheralUtils.notify("5aa2".getBytes(),UUID_SERVER,UUID_CHARWRITE);
LiveDataBus.get().with(LiveDataConstants.BLE_READ).postValue("");
}
};
public BleServerInstance() {
initBle();
}
public static BleServerInstance getInstance() {
return BleManagerHolder.sBleManager;
}
private static class BleManagerHolder {
private static final BleServerInstance sBleManager = new BleServerInstance();
}
public void initBle() {
//实例化工具类
blePeripheralUtils = new BlePeripheralUtils(App.instance);
//初始化一下
blePeripheralUtils.init();
//设置一个结果callback 方便把某些结果传到前面来
blePeripheralUtils.setBlePeripheralCallback(callback);
//实例化需要添加的service信息
BluetoothGattCharacteristicInfo[] bluetoothGattCharacteristicInfos = new BluetoothGattCharacteristicInfo[1];
BluetoothGattDescriptorInfo descriptorInfo = new BluetoothGattDescriptorInfo(UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE);
bluetoothGattCharacteristicInfos[0] = new BluetoothGattCharacteristicInfo(UUID_CHARWRITE,
BluetoothGattCharacteristic.PROPERTY_NOTIFY
| BluetoothGattCharacteristic.PROPERTY_READ
| BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE,
BluetoothGattCharacteristic.PROPERTY_NOTIFY
| BluetoothGattCharacteristic.PERMISSION_READ
| BluetoothGattCharacteristic.PERMISSION_WRITE,
descriptorInfo);
BluetoothGattServiceInfo bluetoothGattServiceInfo1 = new BluetoothGattServiceInfo(UUID_SERVER, BluetoothGattService.SERVICE_TYPE_PRIMARY,bluetoothGattCharacteristicInfos);
//添加需要的service
blePeripheralUtils.addServices(bluetoothGattServiceInfo1);
}
public void closeBle() {
blePeripheralUtils.stopBluetoothLeAdvertiser();
blePeripheralUtils.toDisable();
}
public void open() {
//先打开广播
blePeripheralUtils.startBluetoothLeAdvertiser(BLE_NAME);
}
/**
* 解析 ble data
*
* @param data
*/
private void receiveData(byte[] data) {
//先按照5bb3协议解析,如果解析不对再继续往下走,否则return
List<Byte> datas = Bytes.asList(data);
if (data[0] == (byte) HEAD_5B && data[1] == (byte) HEAD_B3 && judgeByte(datas)){
//视为蓝牙名字通讯
analysisBleNameData(data);
return;
}
if (data.length >= 2 && data[0] == (byte) HEAD1 && data[1] == (byte) HEAD2) {
mBytes.clear();
}
mBytes.addAll(Bytes.asList(data));
// Log.i("haha", "======mBytes==========>" + mBytes.toString());
if (mBytes.get(2) == (byte) CMD_01 && mBytes.size() == mBytes.get(3)) {//接收特定的指令号 长度
if (judgeByte(mBytes)) {
// Log.e("haha", "======和校验通过==========");
analysisBleData(mBytes);
mBytes.clear();
} else {
mBytes.clear();
}
} else if (mBytes.get(2) == (byte) CMD_02 && mBytes.size() == mBytes.get(3)) {//接收特定的指令号 长度
if (judgeByte(mBytes)) {
analysisBleDataSetting(mBytes);
mBytes.clear();
} else {
mBytes.clear();
}
} else {
mBytes.clear();
}
}
/**
* 解析ble setting 数据
* @param list
*/
private void analysisBleDataSetting(List<Byte> list) {
byte[] dataByte = Bytes.toArray(list);
int Left_torque = dataByte[5] & 0xFF;
int Right_torque = dataByte[6] & 0xFF;
int Left_aim_pos = dataByte[7] & 0xFF;
int Right_aim_pos = dataByte[8] & 0xFF;
int Left_leg_fp_stat_H = dataByte[9]&0xFF;
String left_H = Integer.toBinaryString(Left_leg_fp_stat_H);
left_H = String.format("%08d", Long.parseLong(left_H));
int Left_leg_fp_stat_L = dataByte[10]&0xFF;
String left_L = Integer.toBinaryString(Left_leg_fp_stat_L);
left_L = String.format("%08d", Long.parseLong(left_L));
int Right_leg_fp_stat_H = dataByte[11]&0xFF;
String right_H = Integer.toBinaryString(Right_leg_fp_stat_H);
right_H = String.format("%08d", Long.parseLong(right_H));
int Right_leg_fp_stat_L = dataByte[12]&0xFF;
String right_L = Integer.toBinaryString(Right_leg_fp_stat_L);
right_L = String.format("%08d", Long.parseLong(right_L));
int Left_leg_groy = dataByte[13] & 0xFF;
int Right_leg_groy = dataByte[14] & 0xFF;
int Auto_send_switch = dataByte[15] & 0xFF;
BleDataSettingBean dataSettingBean = new BleDataSettingBean(String.valueOf(Left_torque),String.valueOf(Right_torque),String.valueOf(Left_aim_pos),
String.valueOf(Right_aim_pos), left_H,left_L,right_H,right_L,
String.valueOf(Left_leg_groy),String.valueOf(Right_leg_groy),String.valueOf(Auto_send_switch));
LiveDataBus.get().with(LiveDataConstants.BLE_SETTING_DATA).postValue(dataSettingBean);
}
/**
* 足底蓝牙名字设置数据解析
* @param data
*/
private void analysisBleNameData(byte[] data) {
int bleNameStatus = data[4];
byte[] datum = new byte[8];
for (int i = 0; i < 8; i++) {
datum[i] = data[i+5];
}
String mac = ByteUtil.hexBytesToString(datum);
StringBuffer buffer = new StringBuffer();
buffer.append(ByteUtil.hexToString(mac.substring(0,2)));
buffer.append(ByteUtil.hexToString(mac.substring(2,4)));
buffer.append(ByteUtil.hexToString(mac.substring(4,6)));
buffer.append(ByteUtil.hexToString(mac.substring(6,8)));
buffer.append(ByteUtil.hexToString(mac.substring(8,10)));
buffer.append(ByteUtil.hexToString(mac.substring(10,12)));
buffer.append(ByteUtil.hexToString(mac.substring(12,14)));
buffer.append(ByteUtil.hexToString(mac.substring(14,16)));
Log.e("lala", "======ble mac==========>" + buffer.toString());
BleNameBean bean = new BleNameBean(bleNameStatus,buffer.toString().trim());
LiveDataBus.get().with(LiveDataConstants.BLE_NAME_READ).postValue(bean);
}
/**
* 解析数据
* @param data
*/
private void analysisBleData(List<Byte> data) {
// List<Byte> bleData = data.subList(4, data.size() - 2);
// if (bleData.size() < 56) {
// return;
// }
byte[] dataByte = Bytes.toArray(data);
int sys_mode = dataByte[4] & 0xFF;
// Log.i("lala","====sys_mode==>"+ sys_mode);
int sys_fault_H = dataByte[5];
int sys_fault_L = dataByte[6];
// Log.i("lala","====sys_fault_H==>"+ sys_fault_H);
// Log.i("lala","====sys_fault_L==>"+ sys_fault_L);
int sys_fault = ((sys_fault_H << 8)) | (sys_fault_L & 0xFF);
// Log.i("lala","====ands==>"+ sys_fault);
String sys_fault_data = Integer.toBinaryString(sys_fault);
// Log.i("lala","====sys_fault_data==>"+ sys_fault_data);
int save_state = dataByte[7] & 0xFF;
// Log.i("lala","====save_state==>"+ save_state);
int Left_knee_pos_H = dataByte[8];
int Left_knee_pos_L = dataByte[9];
int Left_knee_pos = ((Left_knee_pos_H << 8)) | (Left_knee_pos_L);
// Log.i("lala","====Left_knee_pos==>"+ Left_knee_pos);
int Right_knee_pos_H = dataByte[10];
int Right_knee_pos_L = dataByte[11];
int Right_knee_pos = ((Right_knee_pos_H << 8)) | (Right_knee_pos_L);
// Log.i("lala","====Right_knee_pos==>"+ Right_knee_pos);
int left_leg_groy = dataByte[12];
int right_leg_groy = dataByte[13];
// Log.i("lala","====Left_leg_groy==>"+ Left_leg_groy);
// Log.i("lala","====Right_leg_groy==>"+ Right_leg_groy);
int Left_leg_fp_max_H = dataByte[14];
int Left_leg_fp_max_L = dataByte[15];
int left_leg_fp_max = (Left_leg_fp_max_H << 8) | Left_leg_fp_max_L & 0xFF;
Log.i("lala","====Left_leg_fp_max==>"+ left_leg_fp_max);
int Right_leg_fp_max_H = dataByte[16];
int Right_leg_fp_max_L = dataByte[17];
int right_leg_fp_max = (Right_leg_fp_max_H << 8) | Right_leg_fp_max_L & 0xFF;
Log.i("lala","====Right_leg_fp_max==>"+ right_leg_fp_max);
int Left_leg_fp_sum_H = dataByte[18];
int Left_leg_fp_sum_L = dataByte[19];
int Left_leg_fp_sum = (Left_leg_fp_sum_H << 8) | Left_leg_fp_sum_L & 0xFF;
Log.i("lala","====Left_leg_fp_sum==>"+ Left_leg_fp_sum);
int Right_leg_fp_sum_H = dataByte[20];
int Right_leg_fp_sum_L = dataByte[21];
int Right_leg_fp_sum = (Right_leg_fp_sum_H << 8) | Right_leg_fp_sum_L & 0xFF;
Log.i("lala","====Right_leg_fp_sum==>"+ Right_leg_fp_sum);
int left_leg_fp_1 = dataByte[22] & 0xff;
int left_leg_fp_2 = dataByte[23] & 0xff;
int left_leg_fp_3 = dataByte[24] & 0xff;
int left_leg_fp_4 = dataByte[25] & 0xff;
int left_leg_fp_5 = dataByte[26] & 0xff;
int left_leg_fp_6 = dataByte[27] & 0xff;
int left_leg_fp_7 = dataByte[28] & 0xff;
int left_leg_fp_8 = dataByte[29] & 0xff;
int left_leg_fp_9 = dataByte[30] & 0xff;
int left_leg_fp_10 = dataByte[31] & 0xff;
int left_leg_fp_11 = dataByte[32] & 0xff;
int left_leg_fp_12 = dataByte[33] & 0xff;
int left_leg_fp_13 = dataByte[34] & 0xff;
int left_leg_fp_14 = dataByte[35] & 0xff;
int left_leg_fp_15 = dataByte[36] & 0xff;
int left_leg_fp_16 = dataByte[37] & 0xff;
// Log.i("lala","====left_leg_fp==>"+ left_leg_fp_1 + "==" + left_leg_fp_2 + "=="
// + left_leg_fp_3 + "==" + left_leg_fp_4 + "=="
// + left_leg_fp_5 + "==" + left_leg_fp_6 + "=="
// + left_leg_fp_7 + "==" + left_leg_fp_8 + "=="
// + left_leg_fp_9 + "==" + left_leg_fp_10 + "=="
// + left_leg_fp_11 + "==" + left_leg_fp_12 + "=="
// + left_leg_fp_13 + "==" + left_leg_fp_14 + "=="
// + left_leg_fp_15 + "==" + left_leg_fp_16);
int right_leg_fp_1 = dataByte[38] & 0xff;
int right_leg_fp_2 = dataByte[39] & 0xff;
int right_leg_fp_3 = dataByte[40] & 0xff;
int right_leg_fp_4 = dataByte[41] & 0xff;
int right_leg_fp_5 = dataByte[42] & 0xff;
int right_leg_fp_6 = dataByte[43] & 0xff;
int right_leg_fp_7 = dataByte[44] & 0xff;
int right_leg_fp_8 = dataByte[45] & 0xff;
int right_leg_fp_9 = dataByte[46] & 0xff;
int right_leg_fp_10 = dataByte[47] & 0xff;
int right_leg_fp_11 = dataByte[48] & 0xff;
int right_leg_fp_12 = dataByte[49] & 0xff;
int right_leg_fp_13 = dataByte[50] & 0xff;
int right_leg_fp_14 = dataByte[51] & 0xff;
int right_leg_fp_15 = dataByte[52] & 0xff;
int right_leg_fp_16 = dataByte[53] & 0xff;
// Log.i("lala","====right_leg_fp==>"+ right_leg_fp_1 + "==" + right_leg_fp_2 + "=="
// + right_leg_fp_3 + "==" + right_leg_fp_4 + "=="
// + right_leg_fp_5 + "==" + right_leg_fp_6 + "=="
// + right_leg_fp_7 + "==" + right_leg_fp_8 + "=="
// + right_leg_fp_9 + "==" + right_leg_fp_10 + "=="
// + right_leg_fp_11 + "==" + right_leg_fp_12 + "=="
// + right_leg_fp_13 + "==" + right_leg_fp_14 + "=="
// + right_leg_fp_15 + "==" + right_leg_fp_16);
StringBuffer leftPosData = new StringBuffer();
leftPosData.append(left_leg_fp_1);
leftPosData.append(",");
leftPosData.append(left_leg_fp_2);
leftPosData.append(",");
leftPosData.append(left_leg_fp_3);
leftPosData.append(",");
leftPosData.append(left_leg_fp_4);
leftPosData.append(",");
leftPosData.append(left_leg_fp_5);
leftPosData.append(",");
leftPosData.append(left_leg_fp_6);
leftPosData.append(",");
leftPosData.append(left_leg_fp_7);
leftPosData.append(",");
leftPosData.append(left_leg_fp_8);
leftPosData.append(",");
leftPosData.append(left_leg_fp_9);
leftPosData.append(",");
leftPosData.append(left_leg_fp_10);
leftPosData.append(",");
leftPosData.append(left_leg_fp_11);
leftPosData.append(",");
leftPosData.append(left_leg_fp_12);
leftPosData.append(",");
leftPosData.append(left_leg_fp_13);
leftPosData.append(",");
leftPosData.append(left_leg_fp_14);
leftPosData.append(",");
leftPosData.append(left_leg_fp_15);
leftPosData.append(",");
leftPosData.append(left_leg_fp_16);
StringBuffer rightPosData = new StringBuffer();
rightPosData.append(right_leg_fp_1);
rightPosData.append(",");
rightPosData.append(right_leg_fp_2);
rightPosData.append(",");
rightPosData.append(right_leg_fp_3);
rightPosData.append(",");
rightPosData.append(right_leg_fp_4);
rightPosData.append(",");
rightPosData.append(right_leg_fp_5);
rightPosData.append(",");
rightPosData.append(right_leg_fp_6);
rightPosData.append(",");
rightPosData.append(right_leg_fp_7);
rightPosData.append(",");
rightPosData.append(right_leg_fp_8);
rightPosData.append(",");
rightPosData.append(right_leg_fp_9);
rightPosData.append(",");
rightPosData.append(right_leg_fp_10);
rightPosData.append(",");
rightPosData.append(right_leg_fp_11);
rightPosData.append(",");
rightPosData.append(right_leg_fp_12);
rightPosData.append(",");
rightPosData.append(right_leg_fp_13);
rightPosData.append(",");
rightPosData.append(right_leg_fp_14);
rightPosData.append(",");
rightPosData.append(right_leg_fp_15);
rightPosData.append(",");
rightPosData.append(right_leg_fp_16);
int Left_leg_fp_stat_H = dataByte[54];
String left_H = Integer.toBinaryString(Left_leg_fp_stat_H);
int Left_leg_fp_stat_L = dataByte[55];
String left_L = Integer.toBinaryString(Left_leg_fp_stat_L);
int Right_leg_fp_stat_H = dataByte[56];
String right_H = Integer.toBinaryString(Right_leg_fp_stat_H);
int Right_leg_fp_stat_L = dataByte[57];
String right_L = Integer.toBinaryString(Right_leg_fp_stat_L);
int Auto_send_switch_stat = dataByte[58];
BleDataBean bleDataBean = new BleDataBean(String.valueOf(sys_mode),sys_fault_data,String.valueOf(save_state),String.valueOf(Left_knee_pos),
String.valueOf(Right_knee_pos),String.valueOf(left_leg_groy),String.valueOf(right_leg_groy),String.valueOf(left_leg_fp_max),
String.valueOf(right_leg_fp_max),String.valueOf(Left_leg_fp_sum),String.valueOf(Right_leg_fp_sum),
String.valueOf(left_leg_fp_1),String.valueOf(left_leg_fp_2),String.valueOf(left_leg_fp_3),
String.valueOf(left_leg_fp_4),String.valueOf(left_leg_fp_5),String.valueOf(left_leg_fp_6),
String.valueOf(left_leg_fp_7),String.valueOf(left_leg_fp_8),String.valueOf(left_leg_fp_9),
String.valueOf(left_leg_fp_10),String.valueOf(left_leg_fp_11),String.valueOf(left_leg_fp_12),
String.valueOf(left_leg_fp_13),String.valueOf(left_leg_fp_14),String.valueOf(left_leg_fp_15),
String.valueOf(left_leg_fp_16), String.valueOf(right_leg_fp_1),String.valueOf(right_leg_fp_2),
String.valueOf(right_leg_fp_3),String.valueOf(right_leg_fp_4),String.valueOf(right_leg_fp_5),
String.valueOf(right_leg_fp_6),String.valueOf(right_leg_fp_7),String.valueOf(right_leg_fp_8),
String.valueOf(right_leg_fp_9),String.valueOf(right_leg_fp_10),String.valueOf(right_leg_fp_11),
String.valueOf(right_leg_fp_12),String.valueOf(right_leg_fp_13),String.valueOf(right_leg_fp_14),
String.valueOf(right_leg_fp_15),String.valueOf(right_leg_fp_16),left_H,left_L,right_H,right_L,String.valueOf(Auto_send_switch_stat));
LiveDataBus.get().with(LiveDataConstants.BLE_DATA).postValue(bleDataBean);
}
/**
* 判断是否符合校验
* 和校验、与校验
* @param data
* @return
*/
private boolean judgeByte(List<Byte> data) {
ReentrantLock lock = new ReentrantLock();
lock.lock();
int and =0;
try {
for (int i = 0; i < data.size() - 2; i++) {
and = and + (data.get(i) & 0xff);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
int ands = ((data.get(data.size() - 2)) << 8) | (data.get(data.size() - 1) & 0xFF);
if (ands == and) {
return true;
}
return false;
}
/**
* 包装要发送的数据
* @param valueByteList
* @return
*/
private byte[] build(List<Byte> valueByteList,byte cmd) {
int payloadLength = 0;
if (valueByteList != null && valueByteList.size() > 0) {
payloadLength = valueByteList.size();
}
int length = payloadLength + 6 + 5;//后边5代表5个备用0
byte[] typeArray = new byte[length];
int indexOfTypeArray = 0;
typeArray[indexOfTypeArray++] = (byte) HEAD1;
typeArray[indexOfTypeArray++] = (byte) HEAD2;
typeArray[indexOfTypeArray++] = cmd;
if (valueByteList != null && valueByteList.size() > 0) {
typeArray[indexOfTypeArray++] = (byte)length;
for (int i = 0; i < valueByteList.size(); i++) {
typeArray[indexOfTypeArray++] = valueByteList.get(i);
}
}
for (int i = 0; i < 5; i++) {
typeArray[indexOfTypeArray++] = 0x00;
}
int sum = 0;
for (byte b : typeArray) {
sum += b & 0xFF;
}
byte high = (byte) ((sum >> 8) & 0xFF);
byte low = (byte) (sum & 0xFF);
typeArray[indexOfTypeArray++] = high;
typeArray[indexOfTypeArray++] = low;
return typeArray;
}
/**
* 查询设备数据
*
*/
public void sendData(List<Byte> bleData) {
ArrayList<Byte> array = new ArrayList<>();
array.add(0, (byte) 0X01);
array.addAll(bleData);
byte[] data = build(array, (byte) CMD_01);
Log.i("lala","===send==>"+ Arrays.toString(data));
blePeripheralUtils.notify(data,UUID_SERVER,UUID_CHARWRITE);
// blePeripheralUtils.notify("app data".getBytes(),UUID_SERVER,UUID_CHARWRITE);
}
public void querySettingData() {
ArrayList<Byte> array = new ArrayList<>();
array.add(0, (byte) 0X01);
for (int i = 0; i < 11; i++) {
array.add((byte)0X00);
}
byte[] data = build(array, (byte) CMD_02);
Log.i("lala","===querySettingData==>"+ Arrays.toString(data));
blePeripheralUtils.notify(data,UUID_SERVER,UUID_CHARWRITE);
// blePeripheralUtils.notify("app data".getBytes(),UUID_SERVER,UUID_CHARWRITE);
}
/**
* 查询或者写入ble name
* @param type 0:查询 1:写入
* @param data
*/
public void queryOrWriteBleName(int type,List<String> data) {
byte[] typeArray = new byte[15];
int indexOfTypeArray = 0;
typeArray[indexOfTypeArray++] = (byte) HEAD_5B;
typeArray[indexOfTypeArray++] = (byte) HEAD_B3;
typeArray[indexOfTypeArray++] = 0x0F;
typeArray[indexOfTypeArray++] = 0x01;//指令号
if (type == 0){
typeArray[indexOfTypeArray++] = 0x00;
for (int i = 0; i < 8; i++) {
typeArray[indexOfTypeArray++] = 0x00;
}
} else {
typeArray[indexOfTypeArray++] = 0x01;
//写Mac,字符串转十六进制
if (data != null && data.size() == 2){
String left = data.get(0);
String right = data.get(1);
byte[] leftBytes = left.getBytes(StandardCharsets.US_ASCII);
for (int i = 0; i < leftBytes.length; i++) {
typeArray[indexOfTypeArray++] = leftBytes[i];
}
byte[] rightBytes = right.getBytes(StandardCharsets.US_ASCII);
for (int i = 0; i < rightBytes.length; i++) {
typeArray[indexOfTypeArray++] = rightBytes[i];
}
}
}
int sum = 0;
for (byte b : typeArray) {
sum += b & 0xFF;
}
byte high = (byte) ((sum >> 8) & 0xFF);
byte low = (byte) (sum & 0xFF);
typeArray[indexOfTypeArray++] = high;
typeArray[indexOfTypeArray++] = low;
Log.i("lala","===queryBleName==>"+ Arrays.toString(typeArray));
String ble = ByteUtil.hexBytesToString(typeArray).trim();
Log.i("lala", "====queryBleName==onCharacteristicChanged==========>" + ble);
blePeripheralUtils.notify(typeArray,UUID_SERVER,UUID_CHARWRITE);
}
}
1、BlePeripheralUtils.java
public class BlePeripheralUtils {
private static final String TAG = "BlePeripheralUtils";
private BluetoothAdapter mBluetoothAdapter;
private BluetoothManager bluetoothManager;
private Context context;
private BluetoothLeAdvertiser bluetoothLeAdvertiser;
private BluetoothGattServer bluetoothGattServer;
//连接上的设备
private BluetoothDevice bluetoothDevice;
//ble的状态callback
private BlePeripheralCallback blePeripheralCallback;
/**
* 开启广播的结果callback
*/
private AdvertiseCallback callback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.d(TAG, "BLE advertisement added successfully");
}
@Override
public void onStartFailure(int errorCode) {
Log.e(TAG, "Failed to add BLE advertisement, reason: " + errorCode);
}
};
public BlePeripheralUtils(Context context) {
this.context = context;
}
/**
* 服务事件的回调
*/
private BluetoothGattServerCallback bluetoothGattServerCallback = new BluetoothGattServerCallback() {
/**
* 1.连接状态发生变化时
* @param device :连接的设备
* @param status :操作状态(0是成功,其他值为失败)
* @param newState :当前连接状态(2是已连接 0是已断开)
*/
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
Log.e(TAG, String.format("1.onConnectionStateChange:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("1.onConnectionStateChange:status = %s, newState =%s ", status, newState));
if (newState == 2) {
//连接成功后保存当前的设备
bluetoothDevice = device;
bluetoothGattServer.connect(bluetoothDevice,false);
} else {
//断开后从连接的列表里删除设备
bluetoothDevice = null;
// int index = 0;
// for (int i = 0; i < deviceArrayList.size(); i++) {
// if (deviceArrayList.get(i).getAddress().equals(device.getAddress())) {
// index = i;
// break;
// }
// }
// deviceArrayList.remove(index);
}
//通过回调发送出去
if (blePeripheralCallback != null) {
blePeripheralCallback.onConnectionStateChange(device, status, newState);
}
super.onConnectionStateChange(device, status, newState);
}
@Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
Log.e(TAG, String.format("onServiceAdded:status = %s", status));
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
Log.e(TAG, String.format("onCharacteristicReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("onCharacteristicReadRequest:requestId = %s, offset = %s", requestId, offset));
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
if (blePeripheralCallback != null) {
blePeripheralCallback.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
// super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
}
/**
* 3. onCharacteristicWriteRequest,接收具体的字节
* @param device :连接的设备
* @param requestId :请求的ID(也可以理解为流水号)
* @param characteristic :发送消息使用的characteristic
* @param preparedWrite :是否需要等待后续操作
* @param responseNeeded :是否需要回复
* @param offset : 数据内容偏移
* @param requestBytes :数据内容
*/
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
Log.e(TAG, String.format("3.onCharacteristicWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("3.onCharacteristicWriteRequest:requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, new String(requestBytes)));
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
//通过回调发送出去
if (blePeripheralCallback != null) {
blePeripheralCallback.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, requestBytes);
}
}
/**
* 2.描述被写入时,在这里执行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS... 收,触发 onCharacteristicWriteRequest
* @param device
* @param requestId
* @param descriptor
* @param preparedWrite
* @param responseNeeded
* @param offset
* @param value
*/
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
Log.e(TAG, String.format("2.onDescriptorWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("2.onDescriptorWriteRequest:requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, new String(value)));
// now tell the connected device that this was all successfull
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
}
/**
* 5.特征被读取。当回复响应成功后,客户端会读取然后触发本方法
* @param device
* @param requestId
* @param offset
* @param descriptor
*/
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
Log.e(TAG, String.format("onDescriptorReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("onDescriptorReadRequest:requestId = %s", requestId));
// super.onDescriptorReadRequest(device, requestId, offset, descriptor);
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
}
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
Log.e(TAG, String.format("5.onNotificationSent:device name = %s, address = %s", device.getName(), device.getAddress()));
Log.e(TAG, String.format("5.onNotificationSent:status = %s", status));
}
@Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
Log.e(TAG, String.format("onMtuChanged:mtu = %s", mtu));
}
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
Log.e(TAG, String.format("onExecuteWrite:requestId = %s", requestId));
}
};
/**
* 初始化
*/
public void init() {
bluetoothManager =
(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
toEnable();
}
}
/**
* 打开蓝牙
*/
private boolean toEnable() {
boolean result = false;
try {
if (mBluetoothAdapter == null) {
return false;
}
for (Method temp : Class.forName(mBluetoothAdapter.getClass().getName()).getMethods()) {
if (temp.getName().equals("enableNoAutoConnect")) {
result = (boolean) temp.invoke(mBluetoothAdapter);
}
}
} catch (Exception e) {
//反射调用失败就启动通过enable()启动;
result = mBluetoothAdapter.enable();
e.printStackTrace();
}
return result;
}
/**
* 关闭蓝牙
*/
public void toDisable() {
if (bluetoothDevice != null){
bluetoothGattServer.cancelConnection(bluetoothDevice);
}
if (mBluetoothAdapter != null) {
mBluetoothAdapter.disable();
}
}
/**
* 开启广播
*
* @param bleName:ble设备的名称
*/
public void startBluetoothLeAdvertiser(String bleName) {
//广播设置
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setConnectable(true) //是否被连接
.setTimeout(0) //超时时间
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED) //广播模式
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率
.build();
//广播数据设置
AdvertiseData advertiseData = new AdvertiseData.Builder()
.setIncludeDeviceName(true) //是否在广播中携带设备的名称
.setIncludeTxPowerLevel(true) //是否在广播中携带信号强度
.build();
//扫描回应的广播设置
// AdvertiseData scanResponseData = new AdvertiseData.Builder()
// .setIncludeTxPowerLevel(true) //是否在广播中携带设备的名称
// .addServiceData(new ParcelUuid(parcelUUID), serviceData) //在scanrecord中添加的数据
// .build();
//设置BLE设备的名称
mBluetoothAdapter.setName(bleName);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//开启广播
BluetoothLeAdvertiser bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, callback);
}
},1000);
//开启广播
// BluetoothLeAdvertiser bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
// bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, callback);
}
/**
* 停止广播
*/
public void stopBluetoothLeAdvertiser() {
bluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
bluetoothLeAdvertiser.stopAdvertising(callback);
}
/**
* 添加ble的service
*
* @param serviceInfo:需要添加服务列表
*/
public void addServices(BluetoothGattServiceInfo... serviceInfo) {
//先获取GattServer
bluetoothGattServer = bluetoothManager.openGattServer(context, bluetoothGattServerCallback);
//循环添加需要添加的service
for (BluetoothGattServiceInfo temp : serviceInfo) {
//实例化一个service
BluetoothGattService service_temp = new BluetoothGattService(temp.getUuid(), temp.getServiceType());
//添加其中需要的Characteristic
for (BluetoothGattCharacteristicInfo temp_CharacteristicInfo : temp.getCharacteristicInfos()) {
//实例化需要的characteristic
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(temp_CharacteristicInfo.getUuid(), temp_CharacteristicInfo.getProperties(), temp_CharacteristicInfo.getPermissions());
//看看需不需要添加descriptor
BluetoothGattDescriptorInfo descriptorInfo = temp_CharacteristicInfo.getBluetoothGattDescriptorInfo();
if (descriptorInfo != null) {
//需要就先实例化descriptor
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(descriptorInfo.getUuid(), descriptorInfo.permissions);
//添加到characteristic里
characteristic.addDescriptor(descriptor);
}
//把characteristic添加到service
service_temp.addCharacteristic(characteristic);
}
//把service添加到GattServer
bluetoothGattServer.addService(service_temp);
}
}
/**
* 发送通知给主机
*
* @param data :通知的内容
*/
public boolean notify(byte[] data,UUID UUID_SERVER,UUID UUID_CHARWRITE) {
if (bluetoothDevice == null){
Toast.makeText(context,"当前没有连接设备",Toast.LENGTH_SHORT).show();
return false;
}
BluetoothGattCharacteristic characteristic = getCharacteristic(UUID_SERVER,UUID_CHARWRITE);
if (bluetoothDevice != null && characteristic != null && data != null) {
//设置写操作的类型 WRITE_TYPE_DEFAULT的情况选 底层会自动分包 不用人为分包
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
//把要设置的数据装进characteristic
characteristic.setValue(data);
//发送出去
return bluetoothGattServer.notifyCharacteristicChanged(bluetoothDevice, characteristic, false);
} else {
return false;
}
}
/**
* 获取service下的所有Characteristic
*
* @param serviceUuid :service的UUID
*/
public List<BluetoothGattCharacteristic> getCharacteristicList(UUID serviceUuid) {
//根据UUID获取service
BluetoothGattService service = bluetoothGattServer.getService(serviceUuid);
//获取到了service则获取其中所有的BluetoothGattCharacteristic列表并返回出去
if (service != null) {
return service.getCharacteristics();
} else {
return null;
}
}
/**
* 获取service下的所有Characteristic
*
* @param serviceUuid :service的UUID
* @param characteristicUuid : Characteristic的UUID
*/
public BluetoothGattCharacteristic getCharacteristic(UUID serviceUuid, UUID characteristicUuid) {
//根据UUID获取service
BluetoothGattService service = bluetoothGattServer.getService(serviceUuid);
//获取到了service则根据Characteristic的UUID获取Characteristic
if (service != null) {
return service.getCharacteristic(characteristicUuid);
} else {
return null;
}
}
public BlePeripheralCallback getBlePeripheralCallback() {
return blePeripheralCallback;
}
public void setBlePeripheralCallback(BlePeripheralCallback blePeripheralCallback) {
this.blePeripheralCallback = blePeripheralCallback;
}
}
2、BlePeripheralCallback.java
public interface BlePeripheralCallback {
void onConnectionStateChange(BluetoothDevice device, int status, int newState);
void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic,
boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes);
void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic);
}
3、BluetoothGattCharacteristicInfo.java
public class BluetoothGattCharacteristicInfo {
//Characteristic的UUID
private UUID uuid;
//Characteristic的属性
private int properties;
//Characteristic的权限
private int permissions;
//该service下的Descriptor
private BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo;
public BluetoothGattCharacteristicInfo(UUID uuid,int properties,int permissions,BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo){
this.uuid = uuid;
this.properties = properties;
this.permissions = permissions;
this.bluetoothGattDescriptorInfo = bluetoothGattDescriptorInfo;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public int getProperties() {
return properties;
}
public void setProperties(int properties) {
this.properties = properties;
}
public int getPermissions() {
return permissions;
}
public void setPermissions(int permissions) {
this.permissions = permissions;
}
public BluetoothGattDescriptorInfo getBluetoothGattDescriptorInfo() {
return bluetoothGattDescriptorInfo;
}
public void setBluetoothGattDescriptorInfo(BluetoothGattDescriptorInfo bluetoothGattDescriptorInfo) {
this.bluetoothGattDescriptorInfo = bluetoothGattDescriptorInfo;
}
}
4、BluetoothGattDescriptorInfo.java
public class BluetoothGattDescriptorInfo {
//描述者的UUID
private UUID uuid;
//描述者的权限
int permissions;
public BluetoothGattDescriptorInfo(UUID uuid,int permissions){
this.uuid = uuid;
this.permissions = permissions;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public int getPermissions() {
return permissions;
}
public void setPermissions(int permissions) {
this.permissions = permissions;
}
}
5、BluetoothGattServiceInfo.java
public class BluetoothGattServiceInfo {
//Service的UUID
private UUID uuid;
//服务的类型 SERVICE_TYPE_PRIMARY /SERVICE_TYPE_SECONDARY
private int serviceType;
//该service下的characteristic
private BluetoothGattCharacteristicInfo[] characteristicInfos;
public BluetoothGattServiceInfo(){
}
public BluetoothGattServiceInfo(UUID uuid,int serviceType,BluetoothGattCharacteristicInfo[] characteristicInfos){
this.uuid = uuid;
this.serviceType = serviceType;
this.characteristicInfos = characteristicInfos;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public int getServiceType() {
return serviceType;
}
public void setServiceType(int serviceType) {
this.serviceType = serviceType;
}
public BluetoothGattCharacteristicInfo[] getCharacteristicInfos() {
return characteristicInfos;
}
public void setCharacteristicInfos(BluetoothGattCharacteristicInfo[] characteristicInfos) {
this.characteristicInfos = characteristicInfos;
}
}