前言
天道好轮回,苍天饶过谁。之前开发的OBD检测仪,由于提供的硬件都是经典蓝牙,所以对blebluetooth当时只写了一个小demo就完事了,谁知道这次特么新的检测仪,我们采购的蓝牙模块全部是Ble的,你说坑爹不坑爹,折腾不折腾,典型的不作死就不会死系列。但是,既然选择了,你还有什么办法,只能上啊,然后去官网查资料,在google查资料,期间又有好些文章提到blebluetooth有好多坑,目前我只遇到了一个,因为我测试手机比较少,如果再遇到再说,开始正题。
正文
- 声明权限
/**
*定位权限,是因为高版本需要,而且我这个确定是ble,
*所以我这个apk是不允许在不支持ble的设备上运行的,
*如果你允许,就把true改为false即可,
*另外高版本,这些权限要动态申请的。
*/
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<uses-feature
android:name="android.bluetooth.le"
android:required="true" />
- 申请权限
//TODO--这里我用了easypermission
private static final String[] BLUETOOTH_AND_LOCATION = {
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION};
private static final int RC_BLUETOOTH_PERM = 123;
private void checkBluetoothPermission() {
bluetoothUtils = new BluetoothUtils(this);
if (!EasyPermissions.hasPermissions(this, BLUETOOTH_AND_LOCATION)) {
EasyPermissions.requestPermissions(this, "程序需要以下权限", RC_BLUETOOTH_PERM, BLUETOOTH_AND_LOCATION);
Log.e("mess", "-----no permission------");
} else {
bluetoothAdapter = bluetoothUtils.getBluetoothAdapter();
Log.e("mess", "-----has permission------");
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
Log.e(TAG, "permission granted:" + requestCode);
switch (requestCode) {
case RC_BLUETOOTH_PERM:
bluetoothAdapter = bluetoothUtils.getBluetoothAdapter();
break;
}
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
Log.e(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this).build().show();
}
}
- 扫描设备
//我这里还是用的老版的扫描api
private BluetoothAdapter.LeScanCallback mLeScanCallBack = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.e("mess", "onLeScan.....");
if (device != null && !TextUtils.isEmpty(device.getName())) {
runOnUiThread(new Runnable() {
@Override
public void run() {
deviceListAdapter.addDevice(device);
deviceListAdapter.notifyDataSetChanged();
}
});
}
}
};
/**
*开始搜索之前,一定要停止之前的搜索,而且这个扫描是一个耗时耗资源的操作,所以最好在子线程干,
*或者在主线程也行,但是要及时停止扫描。
*/
private void startSearchDevices(){
if (bluetoothAdapter != null) {
bluetoothAdapter.stopLeScan(mLeScanCallBack);
bluetoothAdapter.startLeScan(mLeScanCallBack);
}
}
4.连接蓝牙
/***
* 这里定义了我的Ble硬件的一些UUID,包括service, notify,write
*
*/
public class BleSppGattAttributes {
private static HashMap<String, String> attributes = new HashMap();
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
//B-0002/B-0004/TLS-01/STB-01
// Service UUID:fee0
// Notify:fee1
// Write:fee1
public static String BLE_SPP_Service = "0000fee0-0000-1000-8000-00805f9b34fb";
public static String BLE_SPP_Notify_Characteristic = "0000fee1-0000-1000-8000-00805f9b34fb";
public static String BLE_SPP_Write_Characteristic = "0000fee2-0000-1000-8000-00805f9b34fb";
public static String BLE_SPP_AT_Characteristic = "0000fee3-0000-1000-8000-00805f9b34fb";
static {
//B-0002/B-0004/TRL-01 SPP Service
attributes.put(BLE_SPP_Service, "BLE SPP Service");
attributes.put(BLE_SPP_Notify_Characteristic, "BLE SPP Notify Characteristic");
attributes.put(BLE_SPP_Write_Characteristic, "BLE SPP Write Characteristic");
attributes.put(BLE_SPP_AT_Characteristic, "BLE SPP AT Characteristic");
}
public static String lookup(String uuid, String defaultName) {
String name = attributes.get(uuid);
return name == null ? defaultName : name;
}
}
核心都在这个Service里面,单设备,多设备都可以用
//TODO---核心监听,这个是必备的,因为考虑到多设备,所以每个gatt的广播,我都带着蓝牙地址发出去的,
//每个蓝牙就监听自己地址的广播就可以了,这样也不会乱
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
//TODO---当连接状态发生改变时,一定会回调这个方法,
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.e(TAG, "onConnectionStateChange:" + gatt.getDevice().getAddress()+",status:"+status);
StringBuffer intentAction = new StringBuffer(gatt.getDevice().getAddress());
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction.append(ACTION_GATT_CONNECTED);
mConnectionState = STATE_CONNECTED;
Log.i(TAG, "Connected to GATT server.");
//TODO---这里我虽然写在了log,但是gatt.discouverServices()是必要的,否则找不到服务
Log.i(TAG, "Attempting to start service discovery:" + gatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction.append(ACTION_GATT_DISCONNECTED);
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
}
broadcastUpdate(intentAction.toString());
}
//TODO---发现服务的回调
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
// 默认先使用 B-0006/TL8266 服务发现
BluetoothGattService service = gatt.getService(UUID.fromString(BleSppGattAttributes.BLE_SPP_Service));
if (service != null) {
//找到服务,继续查找特征值
mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Write_Characteristic));
}
if (mNotifyCharacteristic != null) {
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_DISCOVERED);
//使能Notify
setCharacteristicNotification(gatt, mNotifyCharacteristic, true);
}
if (mWriteCharacteristic == null) //适配没有FEE2的B-0002/04
{
mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
}
if (service == null) {
Log.v("log", "service is null");
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_NO_DISCOVERED);
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.e(TAG, "onCharacteristicRead:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, "onCharacteristicRead");
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
}
}
//接收蓝牙发送的数据回调
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "onCharacteristicChanged:" + gatt.getDevice().getAddress());
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
}
//蓝牙发送数据成功的时候回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.e(TAG, "onCharacteristicWrite:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_WRITE_SUCCESSFUL);
Log.v("log", "Write OK");
}
}
};
然后我们的连接蓝牙代码
//这里用到同步锁,既然是多连接,我就把所有建立的连接存到了Map<address,BluetoothGatt>里面,
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public synchronized boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null || !mBluetoothAdapter.isEnabled()) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
//gat个数是有限的,所以连接的时候,先关闭之前的连接
BluetoothGatt btg = connectionQueue.get(address);
if (btg != null) {
btg.disconnect();
}
//如果已经连接上app,由于超出了范围,链接断了,可以用到btg.connect()去重连;
//当然如果你不想重连,那就断掉之前的连接,重新建立连接即可
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothGatt mBluetoothGatt = null;
//TOTO---这里的连接会有坑,所以做了版本适配,也把坑填上了
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Method connectGattMethod = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
connectGattMethod.setAccessible(true);
mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} catch (Exception ex) {
Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex);
}
}
if (mBluetoothGatt == null) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}
connectionQueue.put(address, mBluetoothGatt);
Log.d(TAG, "Trying to create a new connection." + address + "," + (mBluetoothGatt == null));
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
连接上之后,我们能监听接收的数据,另外关心的就是写数据了
//同样,既然是多链接,肯定是各蓝牙连接写各自的数据
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void writeData(String address, byte[] data) {
if (mWriteCharacteristic != null && data != null) {
mWriteCharacteristic.setValue(data);
BluetoothGatt mBluetoothGatt = connectionQueue.get(address);
if (mBluetoothGatt != null) {
mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);
}
}
}
最后不用的时候,一定要断开连接,如果不主动断开连接,虽然app退出了,但是tcp连接是一直存在的,这样会消耗资源
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void close() {
for (String addr : connectionQueue.keySet()) {
BluetoothGatt mBluetoothGatt = connectionQueue.get(addr);
if (mBluetoothGatt != null) {
mBluetoothGatt.close();
connectionQueue.remove(addr);
mBluetoothGatt = null;
}
}
}
OK,还是把Service整体看下
package kd.com.auroa_brake_detector;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.util.Log;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeMultipleService extends Service {
private final static String TAG = BluetoothLeMultipleService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
//ble characteristic
private BluetoothGattCharacteristic mNotifyCharacteristic;
private BluetoothGattCharacteristic mWriteCharacteristic;
private Map<String, BluetoothGatt> connectionQueue = new LinkedHashMap<>();
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
/**
* intent action 前面加上蓝牙地址,便于区分
*/
public final static String ACTION_GATT_CONNECTED = "kd.com.auroa_brake_detector.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "kd.com.auroa_brake_detector.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "kd.com.auroa_brake_detector.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE = "kd.com.auroa_brake_detector.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "kd.com.auroa_brake_detector.EXTRA_DATA";
public final static String ACTION_WRITE_SUCCESSFUL = "kd.com.auroa_brake_detector.WRITE_SUCCESSFUL";
public final static String ACTION_GATT_SERVICES_NO_DISCOVERED = "kd.com.auroa_brake_detector.GATT_SERVICES_NO_DISCOVERED";
public final static UUID UUID_BLE_SPP_NOTIFY = UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic);
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.e(TAG, "onConnectionStateChange:" + gatt.getDevice().getAddress()+",status:"+status);
StringBuffer intentAction = new StringBuffer(gatt.getDevice().getAddress());
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction.append(ACTION_GATT_CONNECTED);
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction.toString());
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:" + gatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction.append(ACTION_GATT_DISCONNECTED);
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction.toString());
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
// 默认先使用 B-0006/TL8266 服务发现
BluetoothGattService service = gatt.getService(UUID.fromString(BleSppGattAttributes.BLE_SPP_Service));
if (service != null) {
//找到服务,继续查找特征值
mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Write_Characteristic));
}
if (mNotifyCharacteristic != null) {
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_DISCOVERED);
//使能Notify
setCharacteristicNotification(gatt, mNotifyCharacteristic, true);
}
if (mWriteCharacteristic == null) //适配没有FEE2的B-0002/04
{
mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
}
if (service == null) {
Log.v("log", "service is null");
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_NO_DISCOVERED);
}
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.e(TAG, "onCharacteristicRead:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, "onCharacteristicRead");
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "onCharacteristicChanged:" + gatt.getDevice().getAddress());
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
}
//Will call this when write successful
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
Log.e(TAG, "onCharacteristicWrite:" + gatt.getDevice().getAddress());
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(gatt.getDevice().getAddress() + ACTION_WRITE_SUCCESSFUL);
Log.v("log", "Write OK");
}
}
};
private void broadcastUpdate(final String action) {
Log.e(TAG, "broadcastUpdate:" + action);
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
Log.e(TAG, "broadcastUpdate2:" + action);
final Intent intent = new Intent(action);
if (UUID_BLE_SPP_NOTIFY.equals(characteristic.getUuid())) {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
intent.putExtra(EXTRA_DATA, data);
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeMultipleService getService() {
return BluetoothLeMultipleService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "bind.....");
return mBinder;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean initialize() {
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null || !mBluetoothAdapter.isEnabled()) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
//先关闭连接
BluetoothGatt btg = connectionQueue.get(address);
if (btg != null) {
btg.disconnect();
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothGatt mBluetoothGatt = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Method connectGattMethod = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
connectGattMethod.setAccessible(true);
mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} catch (Exception ex) {
Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex);
}
}
if (mBluetoothGatt == null) {
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}
connectionQueue.put(address, mBluetoothGatt);
Log.d(TAG, "Trying to create a new connection." + address + "," + (mBluetoothGatt == null));
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void close() {
for (String addr : connectionQueue.keySet()) {
BluetoothGatt mBluetoothGatt = connectionQueue.get(addr);
if (mBluetoothGatt != null) {
mBluetoothGatt.close();
connectionQueue.remove(addr);
mBluetoothGatt = null;
}
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void setCharacteristicNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
gatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to BLE SPP Notify.
if (UUID_BLE_SPP_NOTIFY.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(BleSppGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void writeData(String address, byte[] data) {
if (mWriteCharacteristic != null && data != null) {
mWriteCharacteristic.setValue(data);
BluetoothGatt mBluetoothGatt = connectionQueue.get(address);
if (mBluetoothGatt != null) {
mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);
}
}
}
}
注册蓝牙广播,假如你连接的蓝牙地址是mAddress,所以注册蓝牙监听广播的时候,要带上地址
public static IntentFilter makeGattUpdateIntentFilter(String address) {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(address+BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(address+BluetoothLeService.ACTION_WRITE_SUCCESSFUL);
intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_SERVICES_NO_DISCOVERED);
return intentFilter;
}
//这样广播就只会接收本蓝牙连接的广播消息了
context.registerReceiver(receiver,makeGattUpdateIntentFilter(address))
结束
核心差不多就这么多,记录一下,方便自己查找,如果有问题,希望多交流交流,因为这个玩意我也是只弄了一周,因为工期比较赶,项目代码不方便上传,如果有问题留言交流吧,或者我的qq:1031012395