316 lines
9.8 KiB
Java
316 lines
9.8 KiB
Java
package xyz.mtfos.btdemo;
|
||
|
||
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.content.Context;
|
||
import android.os.Handler;
|
||
import android.provider.ContactsContract;
|
||
import android.util.Log;
|
||
|
||
import org.apache.commons.lang3.ArrayUtils;
|
||
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.sql.Time;
|
||
import java.util.ArrayList;
|
||
import java.util.Arrays;
|
||
import java.util.HashMap;
|
||
import java.util.UUID;
|
||
|
||
/**
|
||
* Created by jay on 2017/8/9.
|
||
*/
|
||
|
||
public class BLECls {
|
||
// BLEDemo主要代碼
|
||
private BluetoothAdapter mBtAdapter = null;
|
||
private BluetoothGatt mBtGatt = null;
|
||
public int mState = 0;
|
||
private Context mContext;
|
||
private BluetoothGattCharacteristic mWriteCharacteristic = null;
|
||
private BluetoothGattCharacteristic mReadCharacteristric = null;
|
||
|
||
private final String TAG = "BLE_Demo";
|
||
|
||
// 設備連接狀態
|
||
public final int CONNECTED = 0x01;
|
||
public final int DISCONNECTED = 0x02;
|
||
public final int CONNECTTING = 0x03;
|
||
|
||
private ArrayList<HashMap<String, Object>> queue = new ArrayList<>();
|
||
|
||
public int ready = 0;
|
||
private boolean queueRunning = false;
|
||
private boolean scanning = false;
|
||
|
||
// ble address
|
||
public static final String BLEAddr = "B8:27:EB:21:C2:1A";
|
||
// 讀寫相關的Service、Characteristic的UUID
|
||
public static final UUID ServiceUUID = UUID.fromString("dd535b71-8f05-4e30-beb0-6fa7ea3dfc3e");
|
||
public static final UUID TimeUUID = UUID.fromString("00000001-8f05-4e30-beb0-6fa7ea3dfc3e");
|
||
public static final UUID DataUUID = UUID.fromString("00000002-8f05-4e30-beb0-6fa7ea3dfc3e");
|
||
|
||
|
||
// BLE設備連接通信過程中回調
|
||
private BluetoothGattCallback mBtGattCallback = new BluetoothGattCallback() {
|
||
|
||
// 連接狀態發生改變時的回調
|
||
@Override
|
||
public void onConnectionStateChange(BluetoothGatt gatt, int status,
|
||
int newState) {
|
||
|
||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||
mState = CONNECTED;
|
||
Log.d(TAG, "connected OK");
|
||
mBtGatt.discoverServices();
|
||
} else if (newState == BluetoothGatt.GATT_FAILURE) {
|
||
mState = DISCONNECTED;
|
||
Log.d(TAG, "connect failed");
|
||
}
|
||
}
|
||
|
||
// 遠端設備中的服務可用時的回調
|
||
@Override
|
||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||
|
||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||
BluetoothGattService btService = mBtGatt.getService(ServiceUUID);
|
||
if (btService != null) {
|
||
mWriteCharacteristic = btService.getCharacteristic(DataUUID);
|
||
mReadCharacteristric = btService.getCharacteristic(TimeUUID);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 某Characteristic的狀態為可讀時的回調
|
||
@Override
|
||
public void onCharacteristicRead(BluetoothGatt gatt,
|
||
BluetoothGattCharacteristic characteristic, int status) {
|
||
|
||
|
||
}
|
||
|
||
// 寫入Characteristic成功與否的回調
|
||
@Override
|
||
public void onCharacteristicWrite(BluetoothGatt gatt,
|
||
BluetoothGattCharacteristic characteristic, int status) {
|
||
switch (status) {
|
||
case BluetoothGatt.GATT_SUCCESS:
|
||
Log.d(TAG, "write data success");
|
||
break;// 寫入成功
|
||
case BluetoothGatt.GATT_FAILURE:
|
||
Log.d(TAG, "write data failed");
|
||
break;// 寫入失敗
|
||
case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
|
||
Log.d(TAG, "write not permitted");
|
||
break;// 沒有寫入的權限
|
||
}
|
||
queueRunning = false;
|
||
runQueue();
|
||
}
|
||
|
||
// 訂閱了遠端設備的Characteristic信息後,
|
||
// 當遠端設備的Characteristic信息發生改變後,回調此方法
|
||
@Override
|
||
public void onCharacteristicChanged(BluetoothGatt gatt,
|
||
BluetoothGattCharacteristic characteristic) {
|
||
readCharacterisricValue(characteristic);
|
||
}
|
||
|
||
};
|
||
|
||
/**
|
||
* 讀取BluetoothGattCharacteristic中的數據
|
||
*
|
||
* @param characteristic
|
||
*/
|
||
private void readCharacterisricValue(
|
||
BluetoothGattCharacteristic characteristic) {
|
||
byte[] data = characteristic.getValue();
|
||
StringBuffer buffer = new StringBuffer("0x");
|
||
int i;
|
||
for (byte b : data) {
|
||
i = b & 0xff;
|
||
buffer.append(Integer.toHexString(i));
|
||
}
|
||
Log.d(TAG, "read data:" + buffer.toString());
|
||
Log.d(TAG, "read data(as string}:" + new String(data));
|
||
}
|
||
|
||
/**
|
||
* 與指定的設備建立連接
|
||
*
|
||
* @param device
|
||
*/
|
||
public void connect(BluetoothDevice device) {
|
||
|
||
mBtGatt = device.connectGatt(mContext, false, mBtGattCallback);
|
||
mState = CONNECTTING;
|
||
}
|
||
|
||
public boolean isScanning() {
|
||
return scanning;
|
||
}
|
||
|
||
public void disconnect() {
|
||
if (mBtGatt != null) {
|
||
mBtGatt.disconnect();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 初始化
|
||
*
|
||
* @return 如果初始化成功則返回true
|
||
*/
|
||
public boolean init() {
|
||
BluetoothManager btMrg = (BluetoothManager) mContext
|
||
.getSystemService(Context.BLUETOOTH_SERVICE);
|
||
if (btMrg == null)
|
||
return false;
|
||
mBtAdapter = btMrg.getAdapter();
|
||
if (mBtAdapter == null)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
// BLE設備搜索過程中的回調,在此可以根據外圍設備廣播的消息來對設備進行過濾
|
||
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
|
||
|
||
@Override
|
||
public void onLeScan(final BluetoothDevice device, int rssi,
|
||
byte[] scanRecord) {
|
||
|
||
ArrayUtils.reverse(scanRecord);// 數組反轉
|
||
// 將Byte數組的數據以十六進製表示並拼接成字符串
|
||
StringBuffer str = new StringBuffer();
|
||
int i = 0;
|
||
for (byte b : scanRecord) {
|
||
i = (b & 0xff);
|
||
str.append(Integer.toHexString(i));
|
||
}
|
||
String discoveryServceID = str.toString();
|
||
Log.d(TAG, device.getName() + " scanRecord:\n" + discoveryServceID);
|
||
Log.d(TAG, device.getAddress());
|
||
// 查詢是否含有指定的Service UUID信息
|
||
// if (discoveryServceID.indexOf(ServiceUUID.toString().replace("-", "")) != -1) {
|
||
if (device.getAddress().equals(BLEAddr)) {
|
||
|
||
Log.d(TAG, device.getName() + " has available service UUID");
|
||
|
||
// 在這是處理匹配的設備……
|
||
stopScan();
|
||
connect(device);
|
||
}
|
||
|
||
}
|
||
|
||
};
|
||
|
||
/**
|
||
* 開始BLE設備掃瞄
|
||
*/
|
||
public void startScan() {
|
||
scanning = true;
|
||
mBtAdapter.startLeScan(mLeScanCallback);
|
||
}
|
||
|
||
/**
|
||
* 停止BLE設備掃瞄
|
||
*/
|
||
public void stopScan() {
|
||
scanning = false;
|
||
mBtAdapter.stopLeScan(mLeScanCallback);
|
||
}
|
||
|
||
/**
|
||
* 發送數據
|
||
*
|
||
* @param data 待發送的數據,最大長度為20
|
||
*/
|
||
private void sendData(byte[] data) {
|
||
|
||
if (data != null && data.length > 0 && data.length < 21) {
|
||
boolean w = mWriteCharacteristic.setValue(data);
|
||
boolean s = mBtGatt.writeCharacteristic(mWriteCharacteristic);
|
||
System.out.println("send data status ::: " + w + " / " + s);
|
||
if (w && s) {
|
||
Log.d(TAG, "send data OK");
|
||
}
|
||
}
|
||
}
|
||
|
||
public void sendLongData(byte[] data) {
|
||
if (data == null || data.length == 0) return;
|
||
Log.d(TAG, "start send data");
|
||
Log.d(TAG, "Data Length :::: " + data.length);
|
||
byte[] st = new byte[1];
|
||
Arrays.fill(st, (byte) 0x00);
|
||
byte[] ed = new byte[1];
|
||
Arrays.fill(ed, (byte) 0xff);
|
||
HashMap a = new HashMap();
|
||
a.put("type", "w");
|
||
a.put("data", st);
|
||
pushQueue(a);
|
||
|
||
int idx = 0;
|
||
|
||
while (true) {
|
||
int s = idx * 18;
|
||
int e = idx * 18 + 18;
|
||
e = e > data.length ? data.length : e;
|
||
byte[] tmp = Arrays.copyOfRange(data, s, e);
|
||
byte[] tt = new byte[2 + tmp.length];
|
||
tt[1] = (byte) (idx & 0xff);
|
||
tt[0] = (byte) ((idx >> 8) & 0xff);
|
||
for (int i = 2; i < tt.length; i++) {
|
||
if (i - 2 >= tmp.length) break;
|
||
tt[i] = tmp[i - 2];
|
||
}
|
||
|
||
HashMap thash = new HashMap();
|
||
thash.put("type", "w");
|
||
thash.put("data", tt);
|
||
|
||
pushQueue(thash);
|
||
idx++;
|
||
|
||
if (e >= data.length) break;
|
||
}
|
||
|
||
HashMap b = new HashMap();
|
||
b.put("type", "w");
|
||
b.put("data", ed);
|
||
pushQueue(b);
|
||
}
|
||
|
||
private void pushQueue(HashMap d) {
|
||
if (queue == null) queue = new ArrayList<>();
|
||
queue.add(d);
|
||
runQueue();
|
||
}
|
||
|
||
private void runQueue() {
|
||
if (queue == null) queue = new ArrayList<>();
|
||
if (queue.size() < 1 || queueRunning == true) return;
|
||
queueRunning = true;
|
||
HashMap tmp = queue.get(0);
|
||
queue.remove(0);
|
||
if (((String) tmp.get("type")).equals("w")) {
|
||
byte[] d = (byte[]) tmp.get("data");
|
||
sendData(d);
|
||
}
|
||
}
|
||
|
||
public BLECls(Context ctx) {
|
||
this.mContext = ctx;
|
||
}
|
||
|
||
|
||
}
|