Comment forcer programmatically bluetooth découverte de service de basse énergie sur Android sans utiliser cache

J'utilise Android 4.4.2 sur un Nexus 7. J'ai un périphérique bluetooth basse énergie dont les services changent quand il est redémarré. L'application android appelle BluetoothGatt.discoverServices(). Cependant, Android n'interroge le périphérique qu'une seule fois pour découvrir les services, les appels ultérieurs à discoverServices() aboutissent aux données mises en cache du premier appel, même entre les déconnexions. Si je désactive/active L'adaptateur android bt, discoverServices () rafraîchit le cache en interrogeant le périphérique. Être y a-t-il un moyen programmatique pour forcer Android à rafraîchir son cache de services sans désactiver/activer l'adaptateur?

36
demandé sur benchuk 2014-03-24 00:55:34

4 réponses

je viens d'avoir le même problème. Si vous voyez le code source de BluetoothGatt.java vous pouvez voir qu'il ya une méthode appelée 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;
}

cette méthode efface réellement le cache d'un périphérique bluetooth. Mais le problème est que nous n'avons pas accès. Mais à java nous avons réflexion, donc nous pouvons accéder à cette méthode. Voici mon code pour connecter un appareil bluetooth rafraîchissant le cache.

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;
    }
75
répondu Miguel 2014-03-30 17:28:09

en effet la réponse de Miguel fonctionne. Pour utiliser rafraîchdevicecache, j'ai réussi avec cette commande d'appel:

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

cela fonctionne pour OS 4.3 à 5.0 testé avec les périphériques Android et iPhone.

2
répondu Thomas 2015-01-29 15:28:02

Utilisez ce qui suit avant de numériser l'appareil:

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

ceci déconnectera le périphérique et effacera le cache et donc vous pourrez vous reconnecter au même périphérique.

2
répondu Gyapti Jain 2015-02-20 09:40:39

dans certains appareils, même vous déconnectez la socket la connexion ne se terminera pas à cause du cache. Vous devez déconnecter le périphérique distant en utilisant la classe BluetoothGatt. Comme Ci-Dessous

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

Remarque : Cette logique a fonctionné pour moi en chine en fonction des périphériques

2
répondu Satheesh 2017-04-05 09:49:48