首页 文章

如何在不使用缓存的情况下以编程方式强制在Android上强制蓝牙低能耗服务发现

提问于
浏览
36

我在Nexus 7上使用Android 4.4.2 . 我有一个蓝牙低功耗外设,其服务在重新启动时会发生变化 . Android应用程序调用BluetoothGatt.discoverServices() . 然而,Android只查询外围设备一次以发现服务,后续调用discoverServices()会导致第一次调用的缓存数据,甚至断开连接之间 . 如果我禁用/启用Android bt适配器,则discoverServices()通过查询外设来刷新缓存 . 有没有一种程序化的方法来强制Android刷新其'ble服务缓存而不禁用/启用适配器?

4 回答

  • 2

    我刚遇到同样的问题 . 如果您看到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;
    }
    

    该方法实际上清除了蓝牙设备的缓存 . 但问题是我们无法访问它 . 但是在java中我们有reflection,所以我们可以访问这个方法 . 这是我的代码连接刷新缓存的蓝牙设备 .

    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;
        }
    
  • 2

    确实,米格尔的答案有效 . 要使用refreshDeviceCache,我使用此调用顺序成功:

    // Attempt GATT connection
    public void connectGatt(MyBleDevice found) {
        BluetoothDevice device = found.getDevice();
        gatt = device.connectGatt(mActivity, false, mGattCallback);
        refreshDeviceCache(gatt);
    }
    

    这适用于使用Android和iPhone外设测试的OS 4.3到5.0 .

  • 77

    扫描设备前请使用以下命令:

    if(mConnectedGatt != null) mConnectedGatt.close();
    

    这将断开设备并清除缓存,因此您可以重新连接到同一设备 .

  • 2

    在某些设备中,即使断开连接,连接也不会因缓存而终止 . 您需要使用BluetoothGatt类断开远程设备 . 如下

    BluetoothGatt mBluetoothGatt = device.connectGatt(appContext, false, new BluetoothGattCallback() {
            };);
    mBluetoothGatt.disconnect();
    

    注意:这个逻辑在我的设备中适用于我

相关问题