1,本文主要讲解蓝牙数据的搜索–链接–获取数据值–写入数据值;蓝牙Demo
一:搜索蓝牙设备名称
二:建立链接
三:读取传递过来的值
四:写入数据
蓝牙项目该配置的具体事件
<!-- 检测蓝牙状态 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<!-- 增加蓝牙所需要的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
结合自己最近的项目需求,和自身所学所得,代码基本上利用官方的sever服务和gatt链接,只是通过修改获得自己想要的结果,下面就简单介绍一下自己的理解。
一:扫描BLE设备activity
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter(this);
//添加到蓝牙设备
devicelist.setAdapter(mLeDeviceListAdapter);
二:初始化获得一个bluetoothManager,并检测设备是否支持蓝牙
private void checkBluetooth() {
// 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "没有提供蓝牙", Toast.LENGTH_SHORT).show();
//finish();
}
// 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// 检查设备上是否支持蓝牙
if (mBluetoothAdapter == null) {
Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
//finish();
return;
}
}
三:蓝牙控制的服务BluetoothLeService
在这个服务里面有一个很重要的回调函数BluetoothGattCallback(),蓝牙的数据读取和状态改变都会回调这个函数。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
/**
* 判断连接是否成功
* @param gatt
* @param status
* @param newState
*/
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if(status==BluetoothGatt.GATT_SUCCESS) {
//连接成功的时候
if (newState == BluetoothProfile.STATE_CONNECTED) {
//连接成功
intentAction = BroadCast.ACTION_GATT_CONNECTED;
//发送广播
broadcastUpdate(intentAction);
//打印连接服务
Log.i(TAG, "连接到GATT服务器");
//立即去执行发现服务
gatt.discoverServices();
}
//当断开连接的时候
else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//断开连接
intentAction = BroadCast.ACTION_GATT_DISCONNECTED;
//打印断开连接
Log.i(TAG, "与GATT服务器断开连接");
//发送广播
broadcastUpdate(intentAction);
}
}
}
}
四,发现服务
/**
* 发现服务
* @param gatt
* @param status
*/
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
//连接成功
if(status==BluetoothGatt.GATT_SUCCESS){
//发送发现服务的广播
broadcastUpdate(BroadCast.ACTION_GATT_SERVICES_DISCOVERED);
Log.i(TAG,"发现服务是可以的");
}else {
Log.w(TAG, "发现接收到的服务: " + status);//发现设备的时候 发送广播
}
}
五,数据读取和数据改变
/**
* 数据读取
* @param gatt
* @param characteristic
* @param status
*/
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.i("读取出来的值",gatt+" "+characteristic+" "+status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//读取到里面的数据时候发送广播
broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
Log.i(TAG,"");
}
}
/**
* 数据改变
* @param gatt
* @param characteristic
*/
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
}
/**
* 数据描述读取
* @param gatt
* @param descriptor
* @param status
*/
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if(status == BluetoothGatt.GATT_SUCCESS){
BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
broadcastUpdate(BroadCast.ACTION_DATA_AVAILABLE, characteristic);
Log.i(TAG,"success is data");
}
}
六,广播接受和发送数据,重点看如下:
/**
* 发送广播数据处理
* @param action
* @param characteristic
*/
private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic){
final Intent intent = new Intent(action);
// 当为温度值的时候 以及所有的数据处理
if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER_SENSOR_LOCATION)) {
String a = BWDataParser.getTempData(characteristic);
intent.putExtra(BroadCast.EXTRA_DATA, a);
}
// 当为温度值的时候 以及所有的数据处理
else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER)) {
String health_temp = BWDataParser.getTempData(characteristic);
intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY, health_temp);
}
else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_THERMOMETER_NAME)) {
String aa = BWDataParser.getTempData(characteristic);
intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY_TEMPTWO, aa);
}
else if (characteristic.getUuid().equals(UUIDDataBase.UUID_HEALTH_TONGDAONAMEDATE)) {
Log.i("===3333333333===",characteristic.toString());
String tdname = BWDataParser.getTempData(characteristic);
intent.putExtra(BroadCast.EXTRA_DATA_DISPLAY_TONGDAONAME, tdname);
}
sendBroadcast(intent);
}
七,写入数据到蓝牙设备
还有几个重要的函数比如writeCharacteristic(BluetoothGattCharacteristic characteristic)函数,读取蓝牙中数据。
/**
* 写入蓝牙数据的方法
* @param charac
* @param message
* @return boolean
*/
public static boolean writeCharacteristic(BluetoothGattCharacteristic charac,String message){
//check mBluetoothGatt is available
if (bluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
if(charac!=null&&!message.equals(null)&&!message.equals("")){
//int a = Integer.parseInt(message);
byte []a = convertingTobyteArray(message);
charac.setValue(a);
boolean status = bluetoothGatt.writeCharacteristic(charac);
return status;
}else{
return false;
}
}
八:广播的注册事件:
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
九:断开广播与服务
@Override
protected void onDestroy() {
super.onDestroy();
// 断开广播连接
if(isunbind) {
unregisterReceiver(mGattUpdateReceiver);
if(progressDialog!=null){
progressDialog.dismiss();
}
//断开蓝牙服务连接
if(bluetoothService!=null){
BluetoothService.disconnect();
}
//断开服务连接
if(mServiceConnection!=null) unbindService(mServiceConnection);
if(mediaPlayerUtil!=null){
mediaPlayerUtil.mExit();
}
ActivityCollector.finishAll();
isunbind = false;
}
}
十:在发现了有可支持的服务之后会回调Service中的onServicesDiscovered()函数,并发送广播,在官方的demo中发现了可用的Service之后,就查找该BLE设备支持的所有服务和characteristic,在这里不需要查找所有的服务,只需要向蓝牙写数据和读取数据的Service和characteristic的UUID即可。通过查询低功耗蓝牙(BLE)的数据手册可以得到所需要的UUID。
public class GattAttributes {
//温度类型
public static final String TEMPERATURE_TYPE = "00002a1d-0000-1000-8000-00805f9b34fb";
//usual
public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
//温度探头one
public static final String HEALTH_TEMP_MEASUREMENT = "333-0e0d-4bd4-33-9868ddsa";
//温度探头two
public static final String TEMP_DATA_NAME = "900876-a249-4443-a04e-7655750";
//通道名字
public static final String TEMP_DATA_TONGDAONAME = "89765tg-f54d-4abb-aa79-87544ffd21";
}
十一:蓝牙开发的具体思路,关于数据传输的一些服务,在这之前我们得先了解一下一些专业词汇:
1、profile
profile可以理解为一种规范,一个标准的通信协议,它存在于从机中。蓝牙组织规定了一些标准的profile,例如 HID OVER GATT ,防丢器 ,心率计等。每个profile中会包含多个service,每个service代表从机的一种能力。
2、service
service可以理解为一个服务,在ble从机中,通过有多个服务,例如电量信息服务、系统信息服务等,每个service中又包含多个characteristic特征值。每个具体的characteristic特征值才是ble通信的主题。比如当前的电量是80%,所以会通过电量的characteristic特征值存在从机的profile里,这样主机就可以通过这个characteristic来读取80%这个数据
3、characteristic
characteristic特征值,ble主从机的通信均是通过characteristic来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。
4、UUID
UUID,统一识别码,我们刚才提到的service和characteristic,都需要一个唯一的uuid来标识
十二:具体的蓝牙ble开发总结就这些,如果需要完整蓝牙demo,可以进行下载,博主亲自测试完毕,Demo搜索–链接–读取–写入,若有不理解的地方可以私信回复,希望帮助到更多的初学者!