Add files via upload

This commit is contained in:
DXL
2020-08-27 12:31:58 +08:00
committed by GitHub
parent 99401e1d99
commit 0378f9394f
3 changed files with 417 additions and 116 deletions
+116 -116
View File
@@ -1,116 +1,116 @@
package com.proxgrind.chameleon.utils.device.ble;
import androidx.annotation.NonNull;
import com.proxgrind.chameleon.utils.system.LogUtils;
import com.proxgrind.chameleon.utils.tools.ArrayUtils;
import com.proxgrind.chameleon.utils.tools.HexUtil;
import java.util.ArrayList;
public class BLERawUtils {
// 解析!
public static Details[] parse(byte[] raw) {
ArrayList<Details> details = new ArrayList<>(3);
// 02 01 02
// 02 0A 04
// 03 02 F0 FF
// 0C FF 5A 69 63 6F 78 DC 0D 30 02 74 CC
// 06 09 58 54 34 32 33
// 0000000000000000000000000000000000000000000000000000000000000000
for (int i = 0; i < raw.length; ) {
// 分三段取长度字节!
int len = raw[i];
// 必定超过一个字节!
if (len > 1) {
// 足够一帧数据!
if (len < raw.length + i) {
// 建立存储对象!
Details tmp = new Details();
tmp.setLength(len);
tmp.setType(raw[i + 1]);
// 建立一个存放值字节的数组,长度减去类型可以得到有效的值长度!
byte[] bytes = new byte[len - 1];
// 进行值拷贝!
try {
System.arraycopy(raw, i + 2, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
// 存放进对象中!
tmp.setValue(bytes);
// 添加到结果集!
details.add(tmp);
i += (len + 1);
} else {
break;
}
} else {
break;
}
}
return ArrayUtils.list2Arr(details);
}
// 按照某个类型搜索值
public static Details find(int typeByte, Details[] details) {
if (details != null) {
for (Details tmp : details) {
/*LogUtils.d("len: "
+ HexUtil.toHexString(tmp.getLength()) + ", "
+ "type: " + HexUtil.toHexString(tmp.getType()) + ", "
+ "value: " + HexUtil.toHexString(tmp.getValue()) + ", "
+ "str: " + new String(tmp.getValue())
);*/
if (tmp.getType() == typeByte) {
return tmp;
}
}
}
return null;
}
// 直接获得某个类型的值!
public static Details find(int typeByte, byte[] raw) {
// 进行raw分包查询!
BLERawUtils.Details[] details = BLERawUtils.parse(raw);
return BLERawUtils.find(typeByte, details);
}
// 存放详细信息的类!
public static class Details {
public int getLength() {
return length;
}
private void setLength(int length) {
this.length = length;
}
public int getType() {
return type;
}
private void setType(int type) {
this.type = type;
}
public byte[] getValue() {
return value;
}
private void setValue(byte[] value) {
this.value = value;
}
int length;
int type;
byte[] value;
@NonNull
@Override
public String toString() {
return "[Type=" + type + "]" + "[Value=]" + HexUtil.toHexString(value) + "]" + "[Length=" + length + "]";
}
}
}
package com.proxgrind.chameleon.utils.device.ble;
import androidx.annotation.NonNull;
import com.proxgrind.chameleon.utils.system.LogUtils;
import com.proxgrind.chameleon.utils.tools.ArrayUtils;
import com.proxgrind.chameleon.utils.tools.HexUtil;
import java.util.ArrayList;
public class BLERawUtils {
// 解析!
public static Details[] parse(byte[] raw) {
ArrayList<Details> details = new ArrayList<>(3);
// 02 01 02
// 02 0A 04
// 03 02 F0 FF
// 0C FF 5A 69 63 6F 78 DC 0D 30 02 74 CC
// 06 09 58 54 34 32 33
// 0000000000000000000000000000000000000000000000000000000000000000
for (int i = 0; i < raw.length; ) {
// 分三段取长度字节!
int len = raw[i];
// 必定超过一个字节!
if (len > 1) {
// 足够一帧数据!
if (len < raw.length + i) {
// 建立存储对象!
Details tmp = new Details();
tmp.setLength(len);
tmp.setType(raw[i + 1]);
// 建立一个存放值字节的数组,长度减去类型可以得到有效的值长度!
byte[] bytes = new byte[len - 1];
// 进行值拷贝!
try {
System.arraycopy(raw, i + 2, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
// 存放进对象中!
tmp.setValue(bytes);
// 添加到结果集!
details.add(tmp);
i += (len + 1);
} else {
break;
}
} else {
break;
}
}
return ArrayUtils.list2Arr(details);
}
// 按照某个类型搜索值
public static Details find(int typeByte, Details[] details) {
if (details != null) {
for (Details tmp : details) {
/*LogUtils.d("len: "
+ HexUtil.toHexString(tmp.getLength()) + ", "
+ "type: " + HexUtil.toHexString(tmp.getType()) + ", "
+ "value: " + HexUtil.toHexString(tmp.getValue()) + ", "
+ "str: " + new String(tmp.getValue())
);*/
if (tmp.getType() == typeByte) {
return tmp;
}
}
}
return null;
}
// 直接获得某个类型的值!
public static Details find(int typeByte, byte[] raw) {
// 进行raw分包查询!
BLERawUtils.Details[] details = BLERawUtils.parse(raw);
return BLERawUtils.find(typeByte, details);
}
// 存放详细信息的类!
public static class Details {
public int getLength() {
return length;
}
private void setLength(int length) {
this.length = length;
}
public int getType() {
return type;
}
private void setType(int type) {
this.type = type;
}
public byte[] getValue() {
return value;
}
private void setValue(byte[] value) {
this.value = value;
}
int length;
int type;
byte[] value;
@NonNull
@Override
public String toString() {
return "[Type=" + type + "]" + "[Value=]" + HexUtil.toHexString(value) + "]" + "[Length=" + length + "]";
}
}
}
@@ -0,0 +1,157 @@
package com.proxgrind.chameleon.utils.device.ble;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import com.proxgrind.devices.BleSerialControl;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static android.bluetooth.BluetoothDevice.ACTION_BOND_STATE_CHANGED;
/**
* 蓝牙状态监听!
*/
public class BluetoothUtils {
public static BroadcastReceiver startStatusReceicer(Context context, OnStatusChange callback) {
if (callback != null) {
if (!check(context, callback)) return null;
// 创建广播!
BroadcastReceiver blueToothValueReceiver = new BroadcastReceiver() {
public int DEFAULT_VALUE_BULUETOOTH = 1000;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, DEFAULT_VALUE_BULUETOOTH);
switch (state) {
case BluetoothAdapter.STATE_OFF:
callback.onStateOff(context);
break;
case BluetoothAdapter.STATE_ON:
callback.onStateOn(context);
break;
case BluetoothAdapter.STATE_TURNING_ON:
callback.onStateTurningOn(context);
break;
case BluetoothAdapter.STATE_TURNING_OFF:
callback.onStateTurningOff(context);
break;
case BluetoothAdapter.STATE_CONNECTING:
callback.onConnecting(context);
break;
case BluetoothAdapter.STATE_CONNECTED:
callback.onConnected(context);
break;
case BluetoothAdapter.STATE_DISCONNECTING:
callback.onDisconnecting(context);
break;
case BluetoothAdapter.STATE_DISCONNECTED:
callback.onDisconnected(context);
break;
default:
break;
}
}
}
};
//注册广播,蓝牙状态监听
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
context.registerReceiver(blueToothValueReceiver, filter);
return blueToothValueReceiver;
}
return null;
}
public static BroadcastReceiver startActionReceiver(Context context, OnActionChange callback) {
if (callback != null) {
if (!check(context, callback)) return null;
// 创建广播!
BroadcastReceiver blueToothValueReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
callback.onScanStarted(context);
}
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
callback.onScanFinished(context);
}
}
};
//注册广播,蓝牙状态监听
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
context.registerReceiver(blueToothValueReceiver, filter);
return blueToothValueReceiver;
}
return null;
}
private static boolean check(Context context, OnBlueNoSupport callback) {
BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
if (manager == null || manager.getAdapter() == null) {
callback.onBlueNoSupported(context);
return false;
}
return true;
}
public static void stop(BroadcastReceiver receiver, Context context) {
try {
context.unregisterReceiver(receiver);
} catch (Exception ignored) {
}
}
private static class OnBlueNoSupport {
public void onBlueNoSupported(Context context) {
}
}
public static class OnStatusChange extends OnBlueNoSupport {
public void onStateOff(Context context) {
}
public void onStateOn(Context context) {
}
public void onStateTurningOn(Context context) {
}
public void onStateTurningOff(Context context) {
}
public void onConnecting(Context context) {
}
public void onConnected(Context context) {
}
public void onDisconnecting(Context context) {
}
public void onDisconnected(Context context) {
}
}
public static class OnActionChange extends OnBlueNoSupport {
public void onScanStarted(Context context) {
}
public void onScanFinished(Context context) {
}
}
public static boolean isBlueOpen(Context context) {
return BleSerialControl.get().getAdapter().isEnabled();
}
}
+144
View File
@@ -0,0 +1,144 @@
package com.proxgrind.chameleon.utils.device.ble;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ClsUtils {
/**
* 与设备配对 参考源码:platform/packages/apps/Settings.git
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
@SuppressLint("ObsoleteSdkInt")
static public boolean createBond(Class btClass, BluetoothDevice btDevice) {
if (btDevice.getBondState() == BluetoothDevice.BOND_BONDED) return false;
try {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
Method createBondMethod = btClass.getMethod("createBond");
Object obj = createBondMethod.invoke(btDevice);
return obj instanceof Boolean ? (Boolean) obj : false;
} else {
return btDevice.createBond();
}
} catch (Exception e) {
return false;
}
}
/**
* 与设备解除配对 参考源码:platform/packages/apps/Settings.git
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice) {
try {
Method removeBondMethod = btClass.getMethod("removeBond");
Object obj = removeBondMethod.invoke(btDevice);
return obj instanceof Boolean ? (Boolean) obj : false;
} catch (Exception e) {
return false;
}
}
static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice, String str) throws Exception {
byte[] key = str != null ? str.getBytes() : null;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
try {
Method removeBondMethod = btClass.getDeclaredMethod("setPin", byte[].class);
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[]{key});
Log.d("returnValue", "" + returnValue);
} catch (SecurityException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
} else {
return btDevice.setPin(key);
}
}
// 取消用户输入
static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
// cancelBondProcess(btClass, device);
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
return returnValue.booleanValue();
}
// 取消配对
static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelBondProcess");
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
return returnValue.booleanValue();
}
//确认配对
static public void setPairingConfirmation(Class<?> btClass, BluetoothDevice device, boolean isConfirm) throws Exception {
Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation", boolean.class);
setPairingConfirmation.invoke(device, isConfirm);
}
/**
* @param clsShow
*/
static public void printAllInform(Class clsShow) {
try {
// 取得所有方法
Method[] hideMethod = clsShow.getMethods();
int i = 0;
for (; i < hideMethod.length; i++) {
Log.e("method name", hideMethod[i].getName() + ";and the i is:"
+ i);
}
// 取得所有常量
Field[] allFields = clsShow.getFields();
for (i = 0; i < allFields.length; i++) {
Log.e("Field name", allFields[i].getName());
}
} catch (SecurityException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 刷新设备的缓存!
*/
static public void refreshDeviceCache(BluetoothGatt gatt) {
if (gatt == null) return;
/*
* If the device is bonded this is up to the Service Changed characteristic to notify Android that the services has changed.
* There is no need for this trick in that case.
* If not bonded, the Android should not keep the services cached when the Service Changed characteristic is present in the target device database.
* However, due to the Android bug (still exists in Android 5.0.1), it is keeping them anyway and the only way to clear services is by using this hidden refresh method.
*/
if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
/*
* There is a refresh() method in BluetoothGatt class but for now it's hidden. We will call it using reflections.
*/
try {
//noinspection JavaReflectionMemberAccess
final Method refresh = gatt.getClass().getMethod("refresh");
refresh.invoke(gatt);
} catch (Exception ignored) {
}
}
}
}