分享Android 蓝牙4.0(ble)开发的解决方案
|
最近,随着智能穿戴式设备、智能医疗以及智能家居的普及,蓝牙开发在移动开中显得非常的重要。由于公司需要,研究了一下,蓝牙4.0在Android中的应用。 以下是我的一些总结。 1.先介绍一下关于蓝牙4.0中的一些名词吧: 通过ble连接,读写属性类小数据Profile通用的规范。现在所有的ble应用Profile 都是基于GATT (3)、Service是Characteristic的集合。 比如,有个蓝牙ble的血压计。他可能包括多个Servvice,每个Service有包括多个Characteristic 注意:蓝牙ble只能支持Android 4.3以上的系统 SDK>=18 2.以下是开发的步骤: 复制代码 代码如下:BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 2.2获取BluetoothAdapter 复制代码 代码如下:BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter(); 2.3创建BluetoothAdapter.LeScanCallback
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device,int rssi,final byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
String struuid = NumberUtils.bytes2HexString(NumberUtils.reverseBytes(scanRecord)).replace("-","").toLowerCase();
if (device!=null && struuid.contains(DEVICE_UUID_PREFIX.toLowerCase())) {
mBluetoothDevices.add(device);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
2.4.开始搜索设备。 复制代码 代码如下:mBluetoothAdapter.startLeScan(mLeScanCallback); 2.5.BluetoothDevice 描述了一个蓝牙设备 提供了getAddress()设备Mac地址,getName()设备的名称。
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address
* The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The
* connection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt,int,int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG,"BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect. (先前连接的设备。 尝试重新连接)
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
Log.d(TAG,"Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG,"Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device,so we are setting the
// autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this,false,mGattCallback);
Log.d(TAG,"Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
2.7连接到设备之后获取设备的服务(Service)和服务对应的Characteristic。
// Demonstrates how to iterate through the supported GATT
// Services/Characteristics.
// In this sample,we populate the data structure that is bound to the
// ExpandableListView
// on the UI.
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null)
return;
String uuid = null;
ArrayList<HashMap<String,String>> gattServiceData = new ArrayList<>();
ArrayList<ArrayList<HashMap<String,String>>> gattCharacteristicData = new ArrayList<>();
mGattCharacteristics = new ArrayList<>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String,String> currentServiceData = new HashMap<>();
uuid = gattService.getUuid().toString();
if (uuid.contains("ba11f08c-5f14-0b0d-1080")) {//服务的uuid
//System.out.println("this gattService UUID is:" + gattService.getUuid().toString());
currentServiceData.put(LIST_NAME,"Service_OX100");
currentServiceData.put(LIST_UUID,uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String,String>> gattCharacteristicGroupData = new ArrayList<>();
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String,String> currentCharaData = new HashMap<>();
uuid = gattCharacteristic.getUuid().toString();
if (uuid.toLowerCase().contains("cd01")) {
currentCharaData.put(LIST_NAME,"cd01");
} else if (uuid.toLowerCase().contains("cd02")) {
currentCharaData.put(LIST_NAME,"cd02");
} else if (uuid.toLowerCase().contains("cd03")) {
currentCharaData.put(LIST_NAME,"cd03");
} else if (uuid.toLowerCase().contains("cd04")) {
currentCharaData.put(LIST_NAME,"cd04");
} else {
currentCharaData.put(LIST_NAME,"write");
}
currentCharaData.put(LIST_UUID,uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
mCharacteristicCD01 = gattService.getCharacteristic(UUID.fromString("0000cd01-0000-1000-8000-00805f9b34fb"));
mCharacteristicCD02 = gattService.getCharacteristic(UUID.fromString("0000cd02-0000-1000-8000-00805f9b34fb"));
mCharacteristicCD03 = gattService.getCharacteristic(UUID.fromString("0000cd03-0000-1000-8000-00805f9b34fb"));
mCharacteristicCD04 = gattService.getCharacteristic(UUID.fromString("0000cd04-0000-1000-8000-00805f9b34fb"));
mCharacteristicWrite = gattService.getCharacteristic(UUID.fromString("0000cd20-0000-1000-8000-00805f9b34fb"));
//System.out.println("=======================Set Notification==========================");
// 开始顺序监听,第一个:CD01
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD01,true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD02,true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD03,true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD04,true);
}
}
}
2.8获取到特征之后,找到服务中可以向下位机写指令的特征,向该特征写入指令。
public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG,"BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.writeCharacteristic(characteristic);
}
2.9写入成功之后,开始读取设备返回来的数据。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt,int status,int newState) {
String intentAction;
//System.out.println("=======status:" + status);
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG,"Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG,"Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG,"Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt,int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG,"onServicesDiscovered received: " + status);
}
}
//从特征中读取数据
@Override
public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
//System.out.println("onCharacteristicRead");
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE,characteristic);
}
}
//向特征中写入数据
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,int status) {
//System.out.println("--------write success----- status:" + status);
}
/*
* when connected successfully will callback this method this method can
* dealwith send password or data analyze
*当连接成功将回调该方法
*/
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE,characteristic);
if (characteristic.getValue() != null) {
//System.out.println(characteristic.getStringValue(0));
}
//System.out.println("--------onCharacteristicChanged-----");
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt,BluetoothGattDescriptor descriptor,int status) {
//System.out.println("onDescriptorWriteonDescriptorWrite = " + status + ",descriptor =" + descriptor.getUuid().toString());
UUID uuid = descriptor.getCharacteristic().getUuid();
if (uuid.equals(UUID.fromString("0000cd01-0000-1000-8000-00805f9b34fb"))) {
broadcastUpdate(ACTION_CD01NOTIDIED);
} else if (uuid.equals(UUID.fromString("0000cd02-0000-1000-8000-00805f9b34fb"))) {
broadcastUpdate(ACTION_CD02NOTIDIED);
} else if (uuid.equals(UUID.fromString("0000cd03-0000-1000-8000-00805f9b34fb"))) {
broadcastUpdate(ACTION_CD03NOTIDIED);
} else if (uuid.equals(UUID.fromString("0000cd04-0000-1000-8000-00805f9b34fb"))) {
broadcastUpdate(ACTION_CD04NOTIDIED);
}
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt,int status) {
//System.out.println("rssi = " + rssi);
}
};
----------------------------------------------
//从特征中读取数据
@Override
public void onCharacteristicRead(BluetoothGatt gatt,characteristic);
}
}
2.10、断开连接
/**
* Disconnects an existing connection or cancel a pending connection. The
* disconnection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt,int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG,"BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
2.11、数据的转换方法
// byte转十六进制字符串
public static String bytes2HexString(byte[] bytes) {
String ret = "";
for (byte aByte : bytes) {
String hex = Integer.toHexString(aByte & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase(Locale.CHINA);
}
return ret;
}
/**
* 将16进制的字符串转换为字节数组
*
* @param message
* @return 字节数组
*/
public static byte[] getHexBytes(String message) {
int len = message.length() / 2;
char[] chars = message.toCharArray();
String[] hexStr = new String[len];
byte[] bytes = new byte[len];
for (int i = 0,j = 0; j < len; i += 2,j++) {
hexStr[j] = "" + chars[i] + chars[i + 1];
bytes[j] = (byte) Integer.parseInt(hexStr[j],16);
}
return bytes;
}
大概整体就是如上的步骤,但是也是要具体根据厂家的协议来实现通信的过程。 就拿一个我们项目中的demo说一下。 希望本文对大家学习Android蓝牙技术有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- innodb存储引擎修改表共享空间为独立空间
- sql-server-2005 – NHibernate elt字段
- sql-server – SQLBulkCopy行计数完成
- SqlServer 时间函数的应用(DateDiff )
- 数据库 – 什么是postgresql_psycopg2?
- mysql正确安全清空在线慢查询日志slow log的流程
- sqlserver导入数据到Mysql(转)
- sql – 在sybase Server中提取SP和DDL脚本
- [ASPNET2.0]Membership类+SQLServer2005,AspNet
- sql-server-2005 – 用户定义的函数输出进行Nhib
