由于最近项目需要使用了bluetooth ble开发,所以把蓝牙连接ble设备摸索了一遍,希望能帮到各位开发者,有个提示也好。
先说说整体思路
一 打开蓝牙
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null || bluetoothManager.getAdapter() == null) {
ToastUtil.showToast(mContext, "对不起 ,您的机器不具备蓝牙功能");
}
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
//必须是4.3系统以上才支持蓝牙ble设备
Toast.makeText(mContext, “不支持ble设备”, Toast.LENGTH_SHORT).show();
}
bluetoothAdapter = bluetoothManager.getAdapter();
if (!bluetoothAdapter.isEnabled()) {
// 蓝牙没有打开
if (bluetoothAdapter.enable()) {
// 蓝牙打开成功
} else {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
((Activity) mContext).startActivityForResult(enableIntent, BlueToothUtils.BLUE_OPEN_REQUESTCODE);
}
} else {
// 已经打开蓝牙
}
二 搜索蓝牙设备
//打开蓝牙之后就需要搜索设备了
@SuppressWarnings("deprecation")
public void scanLeDevice(final boolean enable) {
if (bluetoothAdapter != null) {
if (enable) {
//控制搜索蓝牙时间
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mScanning) {
mScanning = false;
bluetoothAdapter.stopLeScan(mLeScanCallback);
// 发送设备搜索完成
mHandler.sendEmptyMessage(BLUETOOTH_SEARCHE_END);
}
}
}, 5*1000);
mScanning = true;
bluetoothAdapter.startLeScan(mLeScanCallback);
LogUtils.d("开始搜索设备");
} else {
LogUtils.d("关闭搜索设备");
mScanning = false;
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
}
三 连接蓝牙服务并且监听蓝牙服务
//连接服务
public void startConnectThread(BluetoothDevice device) {
cnntThread = new ConnectThread(device, true);
cnntThread.start();
}
class ConnectThread extends Thread {
public ConnectThread(BluetoothDevice device, boolean secure) {
try {
if (device != null) {
mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
}
} catch (Exception e) {
LogUtils.e("error: " + e);
}
}
@Override
public void run() {
try {
if (bluetoothAdapter != null && bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
if (mBluetoothGatt != null) {
boolean isConnect = mBluetoothGatt.connect();
LogUtils.d("ConnectThread中run方法mBluetoothGatt的连接状态" + isConnect);
}
} catch (Exception e) {
LogUtils.e(e);
return;
}
}
public void cancel() {
if (mBluetoothGatt != null)
mBluetoothGatt.close();
}
}
private final BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
LogUtils.d("onCharacteristicWrite;status=" + status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// 获取蓝牙ble设备返回给你的信息
}
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// 当连接状态发生改变的时候
LogUtils.d("onConnectionStateChange;status=" + newState);
if (BluetoothProfile.STATE_CONNECTED == newState) {
boolean discoverServicesFlag = mBluetoothGatt.discoverServices();
LogUtils.d("发现服务" + discoverServicesFlag);
} else if (BluetoothProfile.STATE_DISCONNECTED == newState) {
// 连接失败
closeBlueTooth();
mHandler.sendEmptyMessage(BLUETOOTH_ERROR);
LogUtils.d("onConnectionStateChange;连接服务失败" + newState);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// 当发现服务的时候
LogUtils.d("onServicesDiscovered;status=" + status);
// 这里判断服务是否连接成功,然后设置监听是否成功,然后再判断与蓝牙设备是否连接成功
if (status == BluetoothGatt.GATT_SUCCESS) {
boolean openListenServiceFlag = openListenService();
if (openListenServiceFlag) {
mHandler.sendEmptyMessage(BLUETOOTH_CONNECTED_SUCCESS);
} else {
closeBlueTooth();
mHandler.sendEmptyMessage(BLUETOOTH_ERROR);
ToastUtil.showToast(mContext, "监听服务失败,请重试");
}
} else {
closeBlueTooth();
mHandler.sendEmptyMessage(BLUETOOTH_ERROR);
//ToastUtil.showToast(mContext, "发现服务失败,请重试");
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
LogUtils.d("onCharacteristicRead;status=" + status);
}
};
/***
* 打开监听服务
*
* @return
*/
private boolean openListenService() {
try {
if (mBluetoothGatt != null) {
String serviceUUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
String characterUUID = "0000ffe4-0000-1000-8000-00805f9b34fb";
BluetoothGattService serv = mBluetoothGatt.getService(UUID.fromString(serviceUUID));
if (serv != null) {
BluetoothGattCharacteristic charcter = serv.getCharacteristic(UUID.fromString(characterUUID));
// 指定当bluetoothGattCharacteristic发生改变的时候,发出通知
boolean isSucess = mBluetoothGatt.setCharacteristicNotification(charcter, true);
return isSucess;
}
}
} catch (Exception e) {
LogUtils.e(e);
}
return false;
}
四 发送指令,获取ble设备返回的指令信息
// 监听server的UUID和character的UUID,这个是需要跟硬件设备开发人员商量的
private String servUUID = "0000ffe5-0000-1000-8000-00805f9b34fb";
private String CharacterUUID = "0000ffe9-0000-1000-8000-00805f9b34fb";
//获取指令byte[]
private void sendCommand(){
/**
*这里的byte[]比如
*byte[] bytes = new bytes[]
bytes[0] = (byte) getDecode("0xBB");
*/
byte[] value = BlueToothUtils.entryValue(userPhone);
runCommandWithUUID(value);
}/***
* 将字符串转化成16进制
*
* @param str
* @return
*/
public static int getDecode(String str) {
return Integer.decode(str);
}
/***
* 发送指令
*
* @param servUUID
* @param CharacterUUID
* @param value
*/
private boolean runCommandWithUUID(byte[] value) {
if (mBluetoothGatt != null) {
BluetoothGattService serv = mBluetoothGatt.getService(UUID.fromString(servUUID));
BluetoothGattCharacteristic charcter = serv.getCharacteristic(UUID.fromString(CharacterUUID));
boolean isSetSucess = charcter.setValue(value);
boolean isWriteSucess = mBluetoothGatt.writeCharacteristic(charcter);
if (!isWriteSucess) {
isWriteSucess = mBluetoothGatt.writeCharacteristic(charcter);
}
// 发送指令完成
LogUtils.d("发送指令完成isSetSucess=" + isSetSucess + ";isWriteSucess=" + isWriteSucess);
if (isWriteSucess) {
//这里应该反馈给mainActivity中
mHandler.sendEmptyMessage(BLUETOOTH_SEND_VALUE_SUCCESS);
return true;
}
}
return false;
}
//蓝牙通知广播,仅作参考
IntentFilter bluetoothFilter = new IntentFilter();
bluetoothFilter.addAction(tBluetoothAdapter.ACTION_STATE_CHANGED);// 蓝牙状态改变的广播
bluetoothFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);// 蓝牙扫描模式广播
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);// 蓝牙搜索状态广播
bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);// 蓝牙搜索中广播
bluetoothFilter.addAction(BluetoothDevice.ACTION_FOUND);// 蓝牙搜索广播
bluetoothFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);// 蓝牙绑定状态广播
getActivity().registerReceiver(mBluetoothStateReciver, bluetoothFilter);
//广播接受者
private BroadcastReceiver mBluetoothStateReciver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == BluetoothAdapter.ACTION_STATE_CHANGED) {
int blueToothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
showToastBlueToothState(blueToothState);
} else if (action == BluetoothAdapter.ACTION_DISCOVERY_FINISHED) {
// 表示搜索结束
MyProcessDialog.closeDialog();
}else if(action == BluetoothDevice.ACTION_FOUND){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("搜索到的蓝牙名称是:"+device.getName());
}
}
};
这里说明一下进制转换,因为android发送指令是16进制的byte[],所以字符串转成byte搞得特别头疼,只能怪自己数学没认真学啊。
首先说明几个函数
1 Integer.decode(String str)这个函数是将十进制/十六进制/八进制的字符串转成整型,如果要按照byte发送的话,还需要强转成byte,也就是Integer.decode(String str).byteValue().
2 Integer.toHexString(i)将int转成16进制的字符串
另外在说一说基础,以免忘记,byte表示1个字节,1个字节是8bit,也就是8个二进制数,
低八位和高八位,例如十进制的12345678,1234表示高4位,5678表示低4位,如果一个16进制数,1111000010101010中11110000表示高八位10101010表示低八位
前面如果有0x就表示16进制,&是一个按位与符号,Integer.toHexString(int i)&0xFF解释:"ff”是一个16进制数化成二进制数就是(11111111)当一个32位二进制数与一个8位二进制数11111111按位与时,这个32位二进制数的高24位都会变成0,低8位会保持原来的数值(因为高24位中的每一位都是与0相与, 当然都是0了,而低8位都是与1相与,所以会保持原值)
计算校验和
private static String getCheckAndStr(byte[] bytes) {
int value = 0;
for (int i = 1; i < bytes.length; i++) {
value += bytes[i];
}
//将int转成16进制字符串
String valueStr = Integer.toHexString(value);
int vl = valueStr.length();
// 获取低八位 16进制
String codeStr = valueStr.substring(vl - 2, vl);
return codeStr;
}