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

mon*_*zie 40 android bluetooth service-discovery bluetooth-lowenergy

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

Mig*_*uel 80

我刚遇到同样的问题.如果您看到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;
}
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这对Galaxy S5不起作用.他们的蓝牙是如此定制,我恨他们. (6认同)
  • Android 9 上不允许反射:https://developer.android.com/about/versions/pie/restrictions-non-sdk-interfaces (2认同)