ble-android-demo/app/src/main/java/xyz/mtfos/btdemo/BLECls.java

316 lines
9.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}