关于Android蓝牙连接问题总结
来源:互联网 发布:中国保险网络大学 编辑:程序博客网 时间:2024/06/05 04:28
最近开始接触Android的蓝牙设备问题,严格意义上来说,也算是第二次接触蓝牙机制了,之前对于蓝牙设备的整个过程,也不是太了解,只是接触了一些自己需要的部分。而这次应该算是比较深入的了解了蓝牙机制的部分吧,所以就总结一下这段时间对蓝牙的个人认识吧
(此图片转自http://blog.csdn.net/l331258747/article/details/55261386)
基本上关于蓝牙的流程,这张图片就说明的差不多了,检测用户是否开启了蓝牙——开启蓝牙——扫描蓝牙设备——选择设备连接——发现服务——注册特征码——断开连接
关于整个流程,一一来说明一下我遇到的问题和总结:
一:蓝牙检测
我们在启用蓝牙模块的时候,还要先声明一下相关的权限问题
<uses-permissionandroid:name="android.permission.BLUETOOTH" />
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />
蓝牙通信之前,需要先确定设备是否支持蓝牙功能,先初始化一个BluetoothAdapter
的实例,
BluetoothAdapter
提供了一个静态方法getDefaultAdapter()
来获得BluetoothAdapter
的实例
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
然后检测蓝牙是否开启并打开蓝牙:
第一种方法:
if(mBluetoothAdapter!=null){
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
第二种方法:
if(mBluetoothAdapter!=null){
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
}
而两种方法,都会提示用户开启蓝牙权限。
二:扫描蓝牙设备
在扫描这里,要多添加一个点,就是关于蓝牙连接状态的广播监听,方便在蓝牙是否连接,断开的时候去做相关的逻辑处理,所以还是有必要了解一下的。
if (mCommonBroadcastReceiver != null) { LocalBroadcastManager.getInstance(this).registerReceiver( mCommonBroadcastReceiver, makeIntentFilter()); //注册蓝牙监听状态改变 BleProfileServiceReadyActivity.this.registerReceiver(mCommonBroadcastReceiver, makeIntentFilter2());}
private static IntentFilter makeIntentFilter2() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); return intentFilter;}注册相关的蓝牙广播监听之后,在监听中做对应的逻辑处理
private BroadcastReceiver mCommonBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { final String action = intent.getAction(); if (BleProfileService.BROADCAST_CONNECTION_STATE.equals(action)) { final int state = intent.getIntExtra( BleProfileService.EXTRA_CONNECTION_STATE, BleProfileService.STATE_DISCONNECTED); switch (state) { case BleProfileService.STATE_CONNECTED: break; case BleProfileService.STATE_DISCONNECTED: break; case BleProfileService.STATE_LINK_LOSS: break; case BleProfileService.STATE_CONNECTING: break; case BleProfileService.STATE_DISCONNECTING: break; default: // there should be no other actions break; } }这里解释一下相关的状态含义:
STATE_DISCONNECTED 状态为断开
STATE_CONNECTING 状态为连接"
STATE_DISCONNECTING 状态为断中
STATE_CONNECTED 状态为连接中
简单的说一下监听方法后,我们在回到主题,关于扫描蓝牙设备的方法:
- //搜索附近所有的外围设备
- mBluetoothAdapter.startLeScan(mLeScanCallback);
- //搜索某些uuid的外围设备。
- mBluetoothAdapter.startLeScan(uuid[] ,mLeScanCallback);
- 停止扫描
- mBluetoothAdapter.stopLeScan(mLeScanCallback);
/* * 扫描结果回调 */private LeScanCallback mLeScanCallback= new LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { if (mLeScanCallback== null) { return; } try { //这里写逻辑代码 } catch (Exception e) { Log.e("", e.toString()); } return; }};
解释一下其中的几个参数,当你扫描回调后,基本就可以搜索到周围的蓝牙设备了(前提是蓝牙开启的状态下),在回调的结果中,分别以后三个参数
BluetoothDevice 表示你搜索的设备对象,一般获取设备的mac地址就是从这个对象获取,方法是getAddress()
rssi 表示的则是设备距离的远近,信号强弱值,有需要这个值可以用数组缓存下来显示scanRecord 表示的则是蓝牙设备的一些属性值,比如serviceUUIDs;serviceData;localName等
三、蓝牙设备连接
关于蓝牙的连接问题,先要说明几个相关类的含义
BluetoothGatt:中央使用和处理数据;
BluetoothGattCallback:中央的回调。
BluetoothGattServer:周边提供数据;
BluetoothGattServerCallback:周边的回调
BluetoothGattService:Gatt服务BluetoothGattCharacteristic:Gatt特性
BluetoothGattDescriptor:Gatt描述
(转自http://blog.csdn.net/vnanyesheshou/article/details/51943870)我们要做的连接操作,就是用其中一个对象来处理的:
BluetoothDevicedevice=mBluetoothAdapter.getRemoteDevice(new_mac);
蓝牙设备对象,由BluetoothAdapter根据设备的mac地址来获取
这里需要注意的一个坑是,mac地址必须是FF:FF:FF:FF这样的形式,这点不同于IOS的适配,如果使用其他的设备地址,会出现异常IllegalArgumentException
BluetoothGatt mBluetoothGatt =device.connectGatt(mContext, false,mGattCallback);
这里的三个参数,分别是上下文对象,是否自动连接,当BluetoothGatt 设备对象不为空的时候,mGattCallback你的连接回调
private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() { @Override //获取连接状态方法,BLE设备连接上或断开时,会调用到此方 public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (DEBUG) Log.d(TAG, "onConnectionStateChange"); if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { showMessage("Bluetooth LE connected"); } else if (status == BluetoothProfile.STATE_DISCONNECTED) { showMessage("Bluetooth LE disconnected"); } } } //成功发现设备的services时,调用此方法 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if ((status == BluetoothGatt.GATT_SUCCESS) && (mBluetoothGatt.getService(SERVICE_UUID) != null)) { showMessage("Discover service Successful !!!"); } } //读写characteristic时会调用到以下方法 @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if ((status == BluetoothGatt.GATT_SUCCESS) && (characteristic.getUuid().equals(CHARACTERISTIC_UUID))) { showMessage(characteristic.getStringValue(0)); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { BluetoothGattCharacteristic mCharacteristic = getCharacteristic(CHARACTERISTIC_UUID); if ((status == BluetoothGatt.GATT_SUCCESS) && (characteristic.getStringValue(0).equals(mCharacteristic.getStringValue(0)))) { showMessage("CharacteristicWrite Successful !!!"); } }};
onConnectionStateChange方法中的
不过这里需要注意的一个很奇葩的问题是,有些时候并不是可以直接连接成功的,这是由于安卓的蓝牙机制问题,在你刚断开蓝牙设备的时候,就快速去做连接操作,有时候是没问题的,但是有时候就会出现status=133问题。(133状态码一般还出现在连接的设备数量超过最大限制上)
所以我们要单独针对此类问题做一次处理,
@Override
public
void
onConnectionStateChange(BluetoothGatt gatt,
int
status,
int
newState) {
String intentAction;
if
(status == BluetoothGatt.GATT_SUCCESS) {
if
(newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = BluetoothConstants.ACTION_GATT_CONNECTED;
mBLEConnectionState = BluetoothConstants.BLE_STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG,
"Connected to GATT server."
);
Log.i(TAG,
"Attempting to start service discovery:"
+ mBluetoothGatt.discoverServices());
}
else
if
(newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = BluetoothConstants.ACTION_GATT_DISCONNECTED;
mBLEConnectionState = BluetoothConstants.BLE_STATE_DISCONNECTED;
close();
// 防止出现status 133
Log.i(TAG,
"Disconnected from GATT server."
);
broadcastUpdate(intentAction);
}
}
else
{
Log.d(TAG,
"onConnectionStateChange received: "
+ status);
intentAction = BluetoothConstants.GATT_STATUS_133;
mBLEConnectionState = BluetoothConstants.BLE_STATE_DISCONNECTED;
close();
// 防止出现status 133
broadcastUpdate(intentAction);
connect(reConnectAddress);
}
}
(转自http://blog.csdn.net/baidu_26352053/article/details/54571688)
四、发现服务,注册特征码
onServiceAdded需要注意我们的特征码一定不能在别的地方注册,因为蓝牙连接是一个耗时操作,如果你提前注册了特征码,很可能注册不成功,一定放在onServiceAdded方法下去注册,否则你会发现根本无法操作蓝牙设备
private final BluetoothGattServerCallback mCallbacks = new BluetoothGattServerCallback() { @Override //获取连接状态方法,BLE设备连接上或断开时,会调用到此方 public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { if (DEBUG) Log.d(TAG, "onConnectionStateChange: newState=" + newState); if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { mDevice = device; String devicename = device.getName(); String address = device.getAddress(); notifyConnected(devicename); beginNotification(); } else if (status == BluetoothProfile.STATE_DISCONNECTED) { stopNotification(); notifyDisconnected(); mDevice = null; } } } //service添加成功会调用此方 @Override public void onServiceAdded(int status, BluetoothGattService service) { if (DEBUG) Log.d(TAG, "onServiceAdded()"); if (status == BluetoothGatt.GATT_SUCCESS) notifyServiceAdded(); } //读写Characteristic,在此获得客户端发来的消息 @Override public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded,int offset, byte[] value) { if (DEBUG) Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite); try{ mCharacteristicString = new String(value); //客户端发来的消息 }catch(Exception e){ } notifyCharacteristicWriteRequest(mCharacteristicString); } } @Override public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { if (DEBUG) Log.d(TAG, "onCharacteristicReadRequest()"); notifyCharacteristicReadRequest(); }};关于其他的蓝牙设备回调,接收发送数据包给蓝牙设备等操作,就要放在回调的其他几个方法了,具体都有相关的说明和标注,就不一一列出了。
五:蓝牙设备断开问题
mBluetoothGatt.disconnect();mBluetoothGatt.close();mBluetoothGatt = null;大致流程就说完了,其中还有很多坑,比如特征码注册问题了,无法正常断开设备问题了,重启蓝牙后无法正常连接设备等,以后再找时间对此单独在写一篇文章吧。欢迎拍砖
- 关于Android蓝牙连接问题总结
- Android 蓝牙连接问题
- 关于android 经典蓝牙开发 使用UUID连接的问题
- Android蓝牙串口连接总结
- Android蓝牙串口连接总结
- 关于蓝牙设备之间的连接问题
- 关于 Android 连接蓝牙的方法
- 关于Android连接蓝牙的方法
- 关于Android蓝牙设备的连接使用
- android关于连接蓝牙socket 通道
- android 蓝牙搜索、配对连接通信总结
- android 蓝牙搜索、配对连接通信总结
- android开发的蓝牙连接问题求助
- android连接蓝牙相关问题及解决方法
- 关于android官方提供的BluetoothChat源码连接不上蓝牙适配器的问题
- 关于android蓝牙开发的一些总结
- 关于android蓝牙通信的问题
- 一个关于android蓝牙通讯的问题
- 集成算法系列之GBM
- android 扫描二维码 生产二维码
- docker环境搭建
- 第十四周项目二
- poj日记(1222)
- 关于Android蓝牙连接问题总结
- java.lang.StackOverflowError 解决办法
- HTTP cookies 详解
- 第十三周——项目一—验证算法(3)验证二叉排序树相关算法
- regflag linux 重启nfs问题及解决
- android资料查看插件
- 解决redis-cli command not found问题
- tail -f 实时查看日志文件
- java List转换为字符串并加入分隔符的一些方法总结