如何以编程方式在Android上强制执行蓝牙低功耗服务发现,而不使用caching
我在Nexus 7上使用Android 4.4.2。我有一个蓝牙低功耗外围设备,当它重新启动时服务会改变。 Android应用程序调用BluetoothGatt.discoverServices()。 然而,Android只查询一次外设以发现服务,随后调用discoverServices()会导致第一次调用的caching数据,即使在断开连接之间也是如此。 如果我禁用/启用Android bt适配器,则discoverServices()通过查询外设来刷新caching。 有没有一种程序化的方式来强制Android刷新其可靠的服务caching而不禁用/启用适配器?
我只是有同样的问题。 如果您看到BluetoothGatt.java的源代码,您可以看到有一个名为refresh()的方法
/** * Clears the internal cache and forces a refresh of the services from the * remote device. * @hide */ public boolean refresh() { if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress()); if (mService == null || mClientIf == 0) return false; try { mService.refreshDevice(mClientIf, mDevice.getAddress()); } catch (RemoteException e) { Log.e(TAG,"",e); return false; } return true; }
这种方法确实从蓝牙设备清除caching。 但问题是我们无法访问它。 但在java中我们有reflection ,所以我们可以访问这个方法。 这里是我的代码来连接刷新caching的蓝牙设备。
private boolean refreshDeviceCache(BluetoothGatt gatt){ try { BluetoothGatt localBluetoothGatt = gatt; Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]); if (localMethod != null) { boolean bool = ((Boolean) localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue(); return bool; } } catch (Exception localException) { Log.e(TAG, "An exception occured while refreshing device"); } return false; } 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 (mBluetoothGatt != null) { Log.d(TAG,"Trying to use an existing mBluetoothGatt for connection."); if (mBluetoothGatt.connect()) { 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; } // We want to directly connect to the device, so we are setting the // autoConnect // parameter to false. mBluetoothGatt = device.connectGatt(MyApp.getContext(), false, mGattCallback)); refreshDeviceCache(mBluetoothGatt); Log.d(TAG, "Trying to create a new connection."); return true; }
事实上米格尔的答案是有效的。 要使用refreshDeviceCache,我使用这个调用顺序成功:
// Attempt GATT connection public void connectGatt(MyBleDevice found) { BluetoothDevice device = found.getDevice(); gatt = device.connectGatt(mActivity, false, mGattCallback); refreshDeviceCache(gatt); }
这适用于使用Android和iPhone外设进行testing的OS 4.3至5.0。
扫描设备前请使用以下方法:
if(mConnectedGatt != null) mConnectedGatt.close();
这将断开设备并清除caching,因此您将能够重新连接到相同的设备。
在某些设备中,即使断开连接,连接也不会因为caching而终止。 您需要使用BluetoothGatt Class断开远程设备的连接。 如下
BluetoothGatt mBluetoothGatt = device.connectGatt(appContext, false, new BluetoothGattCallback() { };); mBluetoothGatt.disconnect();
注意:这个逻辑适用于我在中国的设备