首先,我阅读SOLVED: GATT callback fails to register并采取该帖子中建议的步骤来解决此问题但没有成功。如果您还没有阅读它,那么建议的修复是直接从主线程或使用处理程序进行所有BLE调用。
我正在开发一个BLE应用程序,希望运行一项服务(每10秒调用一次活动)来执行这些任务:
1)Gets list of our products available to connect to (done, works)
2)For each available device:
2a)connect to device
2b)discover services
2c)read 5 characteristics in this fashion:
2c1)read characteristic
2c2)onCharacteristicRead parse data
2c3)when finished with data read next characteristic
2c4)repeat until all are read (this is done using a state var and switch statement)
2d)disconnect from device
2e)connect to next device
2f)repeat until all devices are read from
2g)stopSelf()
所以问题......一切都很有效。我可以执行整个服务启动 {startService(...);在mainActivity} 完成 {stopSelf();在服务中} 6次。
第7次我得到BluetoothGatt注册回调失败。我不知道为什么我能成功运行6次然后第7次失败。
请记住,我正在从主线程进行所有BLE调用,并且已在多个位置的日志cat中进行了确认。
以下是我的代码大纲:
SERVICE.JAVA
private Handler handler = new Handler();
private BluetoothGatt cGatt = null;
private int unitIndex = 0; // keep track of currently connected unit
private int state = 0; //used to keep track of which characteristic to read next
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Service Started...");
//get ArrayList of units
if(units.size > 0)
handler.post(connectNextRunnable); //calls connectNextDevice()
else
stopSelf();
}
private Runnable discoverServices = new Runnable()
{
public void run()
{
cGatt.discoverServices();
}
}
private Runnable readNextValue = new Runnable()
{
public void run()
{
BluetoothGattCharacteristic c = null;
switch(state)
{
//set c to appropriate characteristic
default: // all characteristics read
unitIndex++;
handler.post(connectNextRunnable)
return
}
cGatt.readCharacteristic(c);
}
}
private void connectNextDevice()
{
if(unitIndex == 0)
store System.nanoTime in variable
if(unitIndex >= units.size) //finished will all units
stopSelf();
if(unitIndex < units.size)
cGatt.disconnect //if null
cGatt.connectGatt(this, false, gattCallback)
}
private BluetoothGattCallback gattCallback = new BluetoothGattCallback()
{
public void onConnectionStateChange()
{
handler.post(discoverServices);
}
public void onServicesDeiscovered()
{
handler.post(readNextValue);
}
public void onCharacteristicRead()
{
ParseData();
}
private void ParseData()
{
//do stuff with data
handler.post(readNextValue);
}
}
所以,就像我说的那样,所有BLE内容都是从主线程通过处理程序调用的。该服务从头到尾成功运行了6次。在第7次我得到那个哑巴没有注册回调。
如果您认为相关,我可以提供更多的logcat信息。我没有在原帖中,因为我输出了大量信息来验证收到的数据等。
以下信息是我的服务从头到尾的第7次运行的logcat信息。
08-15 12:00:10.746: I/PMIQ BTS(32027): Service Started...
08-15 12:00:10.746: I/PMIQ BTS(32027): Units: 1
08-15 12:00:10.746: D/AbsListView(32027): unregisterIRListener() is called
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 0
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to pmIQ-IQ130_D93A
08-15 12:00:10.766: I/System.out(32027): main
08-15 12:00:10.766: D/BluetoothGatt(32027): connect() - device: 00:1E:C0:19:D9:3A, auto: false
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp()
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp() - UUID=e9d10870-4b09-451c-a9fa-c6b5f3594a77
08-15 12:00:10.766: I/BluetoothGatt(32027): Client registered, waiting for callback
08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0
08-15 12:00:10.766: I/PMIQ BTS(32027): CONECTION STATE CHANGED...Binder_2
**08-15 12:00:10.766: E/BluetoothGatt(32027): Failed to register callback**
08-15 12:00:10.766: I/PMIQ BTS(32027): Could not connect to null ... 257
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 1
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.766: I/PMIQ BTS(32027): Start Time: 4360642409647
08-15 12:00:10.766: I/PMIQ BTS(32027): End Time: 4360648970925
08-15 12:00:10.766: I/PMIQ BTS(32027): Difference: 6561278
08-15 12:00:10.766: I/PMIQ BTS(32027): Time to complete: 6
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.876: I/PMIQ BTS(32027): ...Service Destroyed
如果你已经在这里,谢谢!我找不到任何有关状态= 133意味着什么的信息?!它仅在回调失败时发生。每隔一次,状态= 0。
08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0
如果有人甚至可以回答这个问题,那可能会对我有所帮助。或者,如果有人能告诉我为什么它只运行6次。任何见解或预感都可能有所帮助!
谢谢大家!
答案 0 :(得分:54)
好吧我已经弄清楚了。这个问题主要是对我在阅读BluetoothGatt
文档时的疏忽。我正在呼叫.disconnect()
,但不是.close()
。由于Galaxy s4一次只能处理6个连接,我的服务只运行了6次。将.close()
添加到我的代码允许它正确关闭连接并释放那些使用过的连接。
Source that made me re-read the docs more carefully!
因此,如果您有相同设备的重复连接,请记住在您的BluetoothGatt对象上使用.close()!!
答案 1 :(得分:11)
经过几个月的研究并拔掉头发,我找到了一个通常没有谈到的解决方案。
您的正常连接请求如下所示:
cGatt.connectGatt(this, false, gattCallback);
还有另一个版本的connectGatt命令,带有第4个参数。此参数指定要连接的蓝牙设备类型。我添加了一个“2”来指定我通过蓝牙LE连接。 (它被称为“运输”,请原谅我,如果我的解释不正确,但它解决了我所有的问题)
试试这个:
cGatt.connectGatt(this, false, gattCallback, 2);
BAM,现在我的#133噩梦结束了(我祈祷)!
答案 2 :(得分:3)
Android OS <6.0:
mBluetoothDevice.connectGatt(context, false, callback);
Android OS> = 6.0:
mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);
最终,需要硬件设备才能完全解决此问题。
答案 3 :(得分:0)
尝试使用下一种解决方法:
私有静态布尔gatt_status_133 = false;
最终处理程序处理程序= new Handler();
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if(status == 133)
{
gatt_status_133=true;
}
else{
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = 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, BluetoothDevice.TRANSPORT_LE);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(gatt_status_133)
{
Log.d(TAG, "Catch issue");
connect(address);
gatt_status_133=false;
}
}
}, 4000);
return true;
}
答案 4 :(得分:0)
在某些设备上,它已通过
mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);
在某些设备上,例如Samsung S7,A8,是ScanSettings.Builder()。setReportDelay(400)//或500ms的问题。它不应为0或大于1000ms。
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
.setReportDelay(400)
.build();
答案 5 :(得分:0)
以某种方式BluetoothLeScanner.startScan()
可以帮助
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mBluetoothAdapter.isEnabled() && mBleScanner != null) {
mBleScanner.stopScan(mLeScanCallback);
}
} else if (status == 133 && newState == BluetoothProfile.STATE_DISCONNECTED) {
if (D) Log.e(TAG, "connectGatt status == 133");
mMainHandler.post(mDisconnectRunnable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mBluetoothAdapter.isEnabled()) {
mBleScanner = mBluetoothAdapter.getBluetoothLeScanner();
mBleScanner.startScan(null, new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(),
mLeScanCallback);
}
mMainHandler.postDelayed(mConnectRunnable, 10000);
}
}
private ScanCallback mLeScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
if (result.getDevice().getAddress().equals(mBluetoothDeviceAddress)) {
mMainHandler.post(mConnectRunnable);
if (mBleScanner != null) {
mBleScanner.stopScan(mLeScanCallback);
mBleScanner = null;
}
}
}
};