概念
- BLE (Bluetooth Low Energy),又叫蓝牙4.0
- 传统经典蓝牙,蓝牙 3.0-
- 单模 & 双模(同时支持BLE和传统蓝牙)
基础概念
-
设备角色
1.中心设备(Centeal):中心设备相对比较强大,用来连接其他外围设备。例如:手机
2.外围设备(Peripheral):一般是非常小的或者简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备,例如小米手环,只能体温计,智能锁等
3.理论上,一个蓝牙主端设备,可同时与7个蓝牙从端设备进行通讯
4.一个从设备只能被一个主设备连接
5.一旦从设备连接上主设备,就停止广播,断开连接则继续广播
6.在任何时刻只能一个设备尝试建立连接 -
GATT
1.GATT(Generic Attribute Profile):通用属性配置文件
2.GATT定义了两个BLE设备通过Service和Characteristic进行通信的Profile
3.中心设备和外设唯一的通信方式就是建立GATT连接
4.GATT通信的双方是C/S关系
5.GATT连接是独占的
6.GATT规定一个智能设备能有一个或者多少个Service -
Service
Service是一个个独立的逻辑项,它包含一个或者多个Characteristic -
Characteristic
Characteristic是最小的逻辑数据单元,他包含一个关联的数据值 -
Descriptor
Description是对Characteristic的描述,例如范围,计量单位等
image.png
//获取智能设备所有的服务Service
List<BluetoothGattService> services=(BluetoothGatt)gatt.getServices();
//获取智能设备某个服务的Service下所有的特征Characteristic
List<BlueToolthGattCharacteristic> characteristics=(BluetoothGattService)service.getCharacteristic();
//获取智能设备的摸个特征
List<BluetoolthGattDescriptors> descriptors=(BluetoothGattCharacteristic)characteristic.getDescriptors();
- UUID
唯一标识码
每一个Service和Characteristic和Descriptor都有一个唯一的标识UUID
UUID可以用16bit和128bit标识。16bit收费,128bit免费,开发中常用128bit的UUID
//获取指定的UUID的Service
public BluetoothGattService getService(UUID uuid);
//获取指定UUID的Characteristic
public BluetoothGattCharacteristic getCharacteristic(UUID uuid);
//获取指定的UUID的Descriptor
public BluetoothGattDescriptor getDescriptor(UUID uuid);
Gatt下有哪些Service,某个Service下有哪些Characteristic,某个Characteristic下有哪些Descriptor,以及他们的UUID都是固件工程师提供!
BLE通信流程
1.主设备APP扫描,搜索外围只能设备
2.简历BLE蓝牙连接
3.基于BLE蓝牙连接进行数据通信
SDK版本前提
- 主设备Android 4.3+(API Level>=18)
- 请求权限 targetSdkVersion <= 22
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
- 如果需要targetSdkVersion >=23
需要获取如下两个权限,GPS定位和电信运营商基站定位权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
主设备打开蓝牙
final BluetoothManager bluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBtAdapter = bluetoothManager.getAdapter();
//未开启蓝牙
if(mBtAdapter!=null&&!mBtAdapter.isEnable()){
//一种方式是程序主动启动蓝牙
mBtAdapter.enable();
//一种方式是采用体统友好提示用户开启蓝牙
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,REQUEST_ENABLE_BT);
}
- 蓝牙的打开和关闭过程如下:
BluetoothAdapter.STATE_OFF:蓝牙关闭状态
BluetoothAdapter.STATE_TURNING_OFF:蓝牙正在关闭状态
BluetoothAdapter.STATE_ON:蓝牙开启状态
BluetoothAdapter.STATE_TURNING_ON:蓝牙正在开启状态
下面通过一个小demo实现通过监听蓝牙状态变化的广播(luetoothAdapter.ACTION_STATE_CHANGED)获取四中蓝牙的状态
1.注册权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
2.编写一个生成128bit的UUID的工具类UUIDUtils.class
public class UUIDUtil
{
private static final String base_uuid_regex = "0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb";
public static boolean isBaseUUID(String uuid)
{
return uuid.toLowerCase().matches("0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb");
}
public static String UUID_128_to_16bit(String uuid, boolean lower_case)
{
if (uuid.length() == 36) {
if (lower_case) {
return uuid.substring(4, 8).toLowerCase();
}
return uuid.substring(4, 8).toUpperCase();
}
return null;
}
public static String UUID_16bit_128bit(String uuid, boolean lower_case)
{
if (lower_case) {
return ("0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb".substring(0, 4) + uuid + "0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb".substring(38)).toLowerCase();
}
return ("0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb".substring(0, 4) + uuid + "0000([0-9a-f][0-9a-f][0-9a-f][0-9a-f])-0000-1000-8000-00805f9b34fb".substring(38)).toUpperCase();
}
}
3.activity中广播监听蓝牙状态变化,设置一个按钮开启蓝牙
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter mBtAdapter;
private static final String TAG = "TAG";
private String bleStateStr = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final BluetoothManager bluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
mBtAdapter = bluetoothManager.getAdapter();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mBroadcastReceiver, intentFilter);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
bleStateStr = "STSTE_OFF 手机蓝牙已关闭";
break;
case BluetoothAdapter.STATE_TURNING_OFF:
bleStateStr = "STSTE_OFF 手机蓝牙正在关闭";
break;
case BluetoothAdapter.STATE_ON:
bleStateStr = "STSTE_OFF 手机蓝牙已开启";
break;
case BluetoothAdapter.STATE_TURNING_ON:
bleStateStr = "STSTE_OFF 手机蓝牙正在开启";
break;
}
Log.i(TAG, bleStateStr);
}
}
};
public void openBluetooth(View view) {
if (!mBtAdapter.isEnabled()) {
mBtAdapter.enable();
} else {
Log.i(TAG, "蓝牙已开启!");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}
}
java
4.开启蓝牙关闭蓝牙是在Log中展示如下
![image.png](https://img.haomeiwen.com/i7312294/2af606e9d4155e5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
网友评论