关于蓝牙ble开发相关知识

2019-11-19  本文已影响0人  林下人水边兵

蓝牙的基础知识

1. 相关权限申请

权限

android:name="android.permission.BLUETOOTH"/>

android:name="android.permission.BLUETOOTH_ADMIN"/>

注意:android6.0后 需要再添加如下权限定位权限 (如下一个就可以了 也可以多个申请)

android:name="android.permission.ACCESS_COARSE_LOCATION"/>

android:name="android.permission.ACCESS_FINE_LOCATION"/>

2. 搜索蓝牙流程

2.1 打开蓝牙(需要在此之前获取蓝牙适配器BluetoothAdapter 才可以 调起打开蓝牙)

 2.1.1 获取蓝牙适配器BluetoothAdapter

BluetoothManager bluetoothManager =

(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter = bluetoothManager.getAdapter();

  2.1.2 权限申请成功后 就可以 打开蓝牙 ,如下是蓝牙是

if(mBluetoothAdapter ==null|| !mBluetoothAdapter.isEnabled()) {

Intent enableBtIntent =newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT);

}

2.2 扫描蓝牙设备

mBluetoothAdapter.startLeScan(mLeScanCallback)

需要注意:搜索是一个不间断的搜索过程,需要我们手动 停止搜索

所以需要 调用mBluetoothAdapter. mBluetoothAdapter.stopLeScan(mLeScanCallback);

具体代码 定时搜索 如下

private voidscanLeDevice(final booleanenable) {

if(enable) {

// Stops scanning after a pre-defined scan period.

mHandler.postDelayed(newRunnable() {

@Override

public voidrun() {

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

},SCAN_PERIOD);

mScanning =true;

mBluetoothAdapter.startLeScan(mLeScanCallback);

}else{

mScanning =false;

mBluetoothAdapter.stopLeScan(mLeScanCallback);

}

关于mLeScanCallback的具体实现

privateBluetoothAdapter.LeScanCallback mLeScanCallback =

newBluetoothAdapter.LeScanCallback() {

@Override

public voidonLeScan(finalBluetoothDevice device, intrssi,

byte[] scanRecord) {

//搜索到蓝牙 将会在该方法回调 , device就是搜索到的蓝牙

}

};

注意:蓝牙搜索过程 是没有帮我们过来重复搜索到蓝牙 ,如果想要把搜索结果放在集合返回,有可能一个设备会重复给搜索到,这个时候需要自己做个过滤,可通过bleDevice 的mac 地址不同进行过滤

2. 连接蓝牙流程

2.1 先理清 将会常操作的几个 类的概念 如下是它们的关系流程图

BluetoothGatt:手机与BLE终端设备建立通信的一个管道,只有有了这个管道,之后的所有读写通知操作都是通过这个来操作

BluetoothGattService:蓝牙设备的服务,每个BluetoothGatt有多个BluetoothGattService,在这里我们把BluetoothGattService比喻成班级。而Bluetoothdevice我们把它比喻成学校,一个学校里面可以有很多班级,也就是说我们每台BLE终端设备拥有多个服务,班级(各个服务)之间通过UUID(唯一标识符)区别

BluetoothGattCharacteristic:蓝牙所拥有的特征 。每个BluetoothGattService有多个BluetoothGattCharacteristic。它是手机与BLE终端设备交换数据的关键,我们做的所有事情,目的就是为了得到它。在这里我们把它比喻成学生,一个班级里面有很多个学生,也就是说我们每个服务下拥有多个特征,学生(各个特征)之间通过UUID(唯一标识符)区别。

理清了我们开始连接蓝牙

2.2连接蓝牙

搜索到蓝牙后 拿到蓝牙对象 BluetoothDevice device 调用如下方法

参数:第一个参数是上下文对象,第二个参数是是否自动连接,这里设置为false,第三个参数就是上面的回调方法

mBluetoothGatt = device.connectGatt(this, false,mGattCallback);

mGattCallback的具体实现

privateBluetoothGattCallbackmGattCallback=newBluetoothGattCallback() {

//连接状态改变的回调

@Override

public voidonConnectionStateChange(BluetoothGatt gatt, intstatus,

intnewState) {

if(newState == BluetoothProfile.STATE_CONNECTED) {

// 连接成功后 必须启调用 服务发现 (discoverServices)

//调用后 当回调 onServicesDiscovered(BluetoothGatt gatt, int status)方法

//才属于真正的成功连接

mBluetoothGatt.discoverServices();

}

}

//发现服务的回调

public voidonServicesDiscovered(BluetoothGatt gatt, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"成功发现服务");

}else{

Log.e(TAG,"服务发现失败,错误码为:"+ status);

}

if(status == BluetoothGatt.GATT_SUCCESS) {

if(mBluetoothGatt !=null&& isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_NOTIFICATION);

booleanb = mBluetoothGatt.setCharacteristicNotification(characteristic, true);

if(b) {

List descriptors = characteristic.getDescriptors();

for(BluetoothGattDescriptor descriptor : descriptors) {

booleanb1 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);

if(b1) {

mBluetoothGatt.writeDescriptor(descriptor);

Log.d(TAG,"startRead: "+"监听收数据");

}

}

}

}

}

//写操作的回调

public voidonCharacteristicWrite (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"写入成功"+ characteristic.getValue());

}

}

//读操作的回调

public voidonCharacteristicRead (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic,intstatus){

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"读取成功"+ characteristic.getValue());

}

}

//数据返回的回调(此处接收BLE设备返回数据)

public voidonCharacteristicChanged (BluetoothGatt gatt,BluetoothGattCharacteristic

characteristic){

}

}

}

当 回调  onServicesDiscovered(BluetoothGatt gatt, int status) 方法 后  就可以拿着    gatt(上文有解释概念) 进行 读写通知 操作了

3 关于 读,写,通知,操作

 写数据

public void startSend(View view) {

if (mBluetoothGatt != null && isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes = new byte[2];

bytes[0] = 04;

bytes[1] = 01;

characteristic.setValue(bytes);

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

mBluetoothGatt.writeCharacteristic(characteristic);

}}

写入成功会回调

public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {

if (status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG, "写入成功" +characteristic.getValue());

}

}

读数据

public void startSend(View view) {

if (mBluetoothGatt != null && isServiceConnected) {

BluetoothGattService gattService = mBluetoothGatt.getService(UUID_SERVICE);

BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID_WRITE);

byte[] bytes = new byte[2];

bytes[0] = 04;

bytes[1] = 01;

characteristic.setValue(bytes);

mBluetoothGatt.readCharacteristic(characteristic);

}

}

读取成功会回调

//读操作的回调

public voidonCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, intstatus) {

if(status == BluetoothGatt.GATT_SUCCESS) {

Log.e(TAG,"读取成功"+characteristic.getValue());

}

}

注意: 在 读写操作过程  不可以 用for 一次性进行操作  会出现阻塞  需要 将读写操作 写入 队列中  一个一个写入  才是比较好的操作  也不会出现堵塞问题

  蓝牙的操作流程  就此结束    在此基础上  可以再次封装一层  代码就不出来了,一下是流程图

上一篇 下一篇

猜你喜欢

热点阅读