Android中BLE连接出现“BluetoothGatt status 133”的解决方法

http://www.loverobots.cn/android-ble-connection-solution-bluetoothgatt-status-133.html

前  言

最近的工作方向一直在低功耗蓝牙方面,也就是BLE(Bluetoooth Low Energy)。要说起蓝牙,之前能够想到的应用也就是蓝牙耳机、蓝牙手柄之类的。本以为蓝牙这个技术会慢慢没落下去,不过,现在随着智能设备的流行,出现了智能手环这样的可穿戴设备,而其实现通信的方式就是蓝牙。

起初,JACK的机器人怀着做整套APP的心态,觉得蓝牙模块无非是了解一下协议,模仿一下类似实现方式就可以了。直到折腾了一个月后才发现,BLE真TM是个大坑(额,爆粗口了,大家请见谅...),不仅涉及到应用层,还涉及到底层协议栈,需要设置从设备(Peripheral)的话还得会单片机、C语言的混合编程。而最坑的一点是,它还不稳定——不稳定还开发个毛线啊!!!所以,开发的重点之一也包括,解决稳定性问题......

这篇文章先重点记录一下遇到的这个“BluetoothGatt status 133”问题,后续会把相关经验慢慢整理出来分享给大家,也为自己将来再次遇到蓝牙开发时做个知识储备。

BluetoothGatt status 133

首先简单给大家解释下什么是BLE中的“BluetoothGatt status 133”。

在BLE通信中,或者说整个蓝牙通信中,都会经过以下基本步骤:

  • 发现设备->配对/绑定设备->建立连接->数据通信

status 133这个错误状态就出现在BLE通信步骤中的“建立连接”过程中,而这个错误也是网络上进行BLE开发基本都会遇到的一个错误。但是,因为BLE开发还属于比较前沿的技术(公司大牛说的,感觉也还算吧),可供查阅参考的资料大部分还是来自国外的英文资料,国内可供参考的实在是少之又少。

如果有小伙伴在百度上搜索一下BLE相关问题,经常会看到有一些人在提问,然后下面一大片全都是统一回复——“我也遇到了这个问题,楼主解决了请分享一下......”。

而JACK的机器人遇到此问题的情况是,在与一台从设备建立连接后,退出测试DEMO,同时调用了各种释放资源的方法后,再次进入DEMO,与从设备建立连接会出现无法成功建立连接的问题,只要重复多次进入就又可以成功。

而根据stackoverflow上的相关提问:

Android中BLE连接出现“BluetoothGatt status 133”的解决方法

可以发现解决此错误的重点是“在再次和从设备建立连接时,需要首先调用BluetoothGatt的close()释放掉之前的连接资源”,而原因是对于主设备来说,与从设备的连接数量是有限制的,比如其中提到的针对Galaxy s4手机的6个连接数量限制。

那么,重点还是回到连接资源的释放问题。下面看看JACK的机器人的解决方法,代码片段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
     @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);
         }
     }
 
     @Override
     public void onServicesDiscovered(BluetoothGatt gatt, int status) {
         if (status == BluetoothGatt.GATT_SUCCESS) {
             Log.d(TAG, "mBluetoothGatt = " + mBluetoothGatt);
             broadcastUpdate(BluetoothConstants.ACTION_GATT_SERVICES_DISCOVERED);
             BluetoothGattService gattService = mBluetoothGatt
                     .getService(UUID.fromString(UUIDS.KARINGUPGRADE_SERVICE_UUID));
             if (gattService == null ) {
                 showMessage( "gattService not found!" );
                 broadcastUpdate(BluetoothConstants.DEVICE_DOES_NOT_SUPPORT_UART);
                 return ;
             }
             Log.d(TAG, "onServicesDiscovered************************gattService=" + gattService);
             BluetoothGattCharacteristic character = gattService
                     .getCharacteristic(UUID.fromString(UUIDS.RX_CHAR_UUID));
             enableRXNotification( true , character);
         } else {
             Log.d(TAG, "onServicesDiscovered received: " + status);
         }
     }
 
     @Override
     public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
         if (status == BluetoothGatt.GATT_SUCCESS) {
             broadcastUpdate(BluetoothConstants.ACTION_DATA_AVAILABLE, characteristic);
         }
     }
 
     @Override
     public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
         broadcastUpdate(BluetoothConstants.ACTION_DATA_AVAILABLE, characteristic);
     }
};
 
public void setReConnectAddress(String address) {
     reConnectAddress = address;
}
 
public boolean connect( final String address) {
     if (mBluetoothAdapter == null ) {
     Log.w(TAG, "BluetoothAdapter not initialized." );
     return false ;
     }
     if (address == null ) {
     Log.w(TAG, "Unspecified address." );
     }
     if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null ) {
     Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection." );
     if (mBluetoothGatt.connect()) {
     mBLEConnectionState = BluetoothConstants.BLE_STATE_CONNECTING;
     return true ;
     } else {
     return false ;
     }
     }
     final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
     if (device == null ) {
     Log.w(TAG, "Device not found. Unable to connect." );
     return false ;
     }
     mBluetoothGatt = device.connectGatt( this , false , mGattCallback);
     Log.d(TAG, "Trying to create a new connection." );
     mBluetoothDeviceAddress = address;
     Log.d(TAG, "BluetoothDeviceAddress is :" + mBluetoothDeviceAddress);
     mBLEConnectionState = BluetoothConstants.BLE_STATE_CONNECTING;
     return true ;
     }
 
public void close() {
     if (mBluetoothGatt == null ) {
         return ;
     }
     Log.w(TAG, "mBluetoothGatt closed" );
     mBluetoothDeviceAddress = null ;
     disconnect();
     mBluetoothGatt.close();
     mBluetoothGatt = null ;
}

注意看重写的BluetoothGattCallback中onConnectionStateChange()方法中的两个close()方法,此方法调用了mBluetoothGatt.close()用来释放当前的Gatt连接资源,同时在判断为status 133状态时,也就是“status != BluetoothGatt.GATT_SUCCESS”时,在close()方法后会再次调用connect(reConnectAddress)方法,尝试与从设备再次建立连接,直到连接上为止(这里可以做个尝试次数限制)。

其中的reConnectAddress为本次想要连接到的目标从设备蓝牙MAC地址。可以在外部的连接方法中调用setReConnectAddress(String address)方法进行设置。

好了,知道了问题的原因,解决方法其实也就不难了,那么这篇就到这里了。

关于蓝牙方面的内容,希望有相关经验的小伙伴能够在下方留言处多多交流,JACK的机器人在之后的时间也会分享更多相关的经验技巧,感谢大家的支持,谢谢。


  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值