一、蓝牙简介
经典蓝牙和低功耗蓝牙的区别:
https://blog.csdn.net/zqf_888/article/details/80982337
我下面主要介绍的低功耗蓝牙
蓝牙的一系列操作过程:
1、搜索其他蓝牙设备
2、查询适配蓝牙
3、建立RFCOMM通道
4、通过发现服务连接其他蓝牙设备
5、交换数据
6、管理多项连接
二、蓝牙开发常用类
BluetoothAdapter:代表类一个本地的蓝牙适配器。他是所有蓝牙交互的入口点。利用它你可以发现其他蓝牙,查询绑定了的设备,使用已知的的MAC地址实例化一个蓝牙设备和建立一个服务端来监听来自其他设备的连接。
BluetoothDevice:表示远程的蓝牙设备。使用该类对象可以进行远程蓝牙设备的连接请求,获取该设备的相关信息(如设备 名称和地址)。
权限设置:
<uses-permission android:name=android.permission.BLUETOOTH" />`
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />`
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
三、蓝牙实现流程
判断是否支持蓝牙
public BluetoothAdapter getAdapter(Context context){
synchronized(this){
if(mAdapter==null){
BluetoothManager manger = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE);
this.mAdapter = manager.getAdapter();
if(isSupportLollipop)){
mScanner = mAdapter.getBluetoothLeScanner();
}
}
}
return this.mAdapter;
}
/**
* 设备是否支持蓝牙 true为支持
* @return
*/
public boolean isSupportBlue(){
return mBluetoothAdapter != null;
}
3.判断蓝牙是否开启
/**
* 蓝牙是否打开 true为打开
* @return
*/
public boolean isBlueEnable(){
return isSupportBlue() && mBluetoothAdapter.isEnabled();
}
if(!mBluetoothAdapter.isEnabled()){
//弹出对话框提示用户是后打开
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
//不做提示,直接打开,不建议用下面的方法,有的手机会有问题。
// mBluetoothAdapter.enable();
}
开始扫描搜索蓝牙设备:
public void scanLenDevice(final boolean isEnable,long scanPeriod){
if(isEnable){
if(isScanning) return;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isScanning = false;
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP){
if (mBluetoothAdapter.getBluetoothLeScanner() == null) {
return;
}
mBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
}else {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
},scanPeriod);
isScanning = true;
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.LOLLIPOP){
if (mBluetoothAdapter.getBluetoothLeScanner() == null) {
return;
}
mBluetoothAdapter.getBluetoothLeScanner().startScan(mScanCallback);
}else {
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}else {
isScanning = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
} else {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
}
mBluetoothAdapter.startLeScan(callback);
private LeScanCallback callback = new LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
//device为扫描到的BLE设备
if(device.getName() == "目标设备名称"){
//获取目标设备
targetDevice = device;
}
}
};
连接设备
连接设备之前先停止搜索设备
mBluetoothAdapter.stopLeScan(callback);
public BluetoothGatt connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback);
BluetoothGatt mGatt = mDevice.connectGatt(mActivity, false, gattCallback);
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
TelinkLog.d("------onConnectionStateChange");
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt.discoverServices();
//TelinkLog.d("------连接成功,启动服务发现" );
} else {
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
for (BluetoothGattService gattService : services) {
if (gattService.getUuid().equals(MAC_SERVICE_UUID)) {
service = gattService;
for (BluetoothGattCharacteristic gattCharacteristic : service.getCharacteristics()) {
if (gattCharacteristic.getUuid().equals(MAC_CHARACTERISTIC_UUID)) {
characteristic = gattCharacteristic;
}
}
}
}
gatt.setCharacteristicNotification(characteristic, true);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
if (ByteUtil.getBytesString(characteristic.getValue()).contains("4f 4b")) {
// TelinkLog.d("-----数据返回通知-" + ByteUtil.getBytesString(characteristic.getValue()));
//TelinkLog.d("-----mMacAddress-" + mMacAddress);
} else {
mHandler.obtainMessage(MESSAGE_UPDATE_TIP, "MAC写入失败,请重试").sendToTarget();
}
}
};
服务发现
当连接到蓝牙设备的时候,就会回调BluetoothGattCallback里的onConnectionStateChange方法
拿到连接状态,如果 status为BluetoothGatt.GATT_SUCCESS,那么就算连接成功。
当连接成功的时候,接下来的一步就是服务发现,调用如下代码
gatt.discoverServices();
进行通信
获取负责通信的BluetoothGattCharacteristic
通信服务中包含负责读写的BluetoothGattCharacteristic,且分别称为notifyCharacteristic和writeCharacteristic。其中notifyCharacteristic负责开启监听,也就是启动收数据的通道,writeCharacteristic负责写入数据。
开启监听
mBluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(UUID
.fromString
("00002902-0000-1000-8000-00805f9b34fb"));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
若开启监听成功则会回调BluetoothGattCallback中的onDescriptorWrite()方法,处理方式如下:
@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//开启监听成功,可以像设备写入命令了
Log.e(TAG, "开启监听成功");
}
};
写入数据
public void writeCharacteristic(String data) {
if (characteristic != null) {
characteristic.setValue(ByteUtil.parseHexStringToArray(data));
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
if (mGatt.writeCharacteristic(characteristic)) {
TelinkLog.d("-----写入成功");
} else {
TelinkLog.d("-----写入失败");
}
}
接收数据
若写入指令成功则回调BluetoothGattCallback中的onCharacteristicWrite()方法,说明将数据已经发送给下位机。
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, "发送成功");
}
super.onCharacteristicWrite(gatt, characteristic, status);
}
若发送的数据符合通信协议,则下位机会向上位机回复相应的数据。发送的数据通过回调onCharacteristicChanged()方法获取,其处理方式如下:
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// value为设备发送的数据,根据数据协议进行解析
byte[] value = characteristic.getValue();
}
通过向下位机发送指令获取下位机的回复数据,即可完成与设备的通信过程
断开连接
当与设备完成通信之后之后一定要断开与设备的连接。调用以下方法断开与设备的连接:
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
https://www.jianshu.com/p/a27f3ca027e3