Comment savoir par programmation si un appareil Bluetooth est connecté?

86

Je comprends comment obtenir une liste des appareils couplés, mais comment puis-je savoir s'ils sont connectés?

Cela doit être possible car je les vois dans la liste des appareils Bluetooth de mon téléphone et cela indique leur statut de connexion.

dchappelle
la source

Réponses:

155

Ajoutez l'autorisation Bluetooth à votre AndroidManifest,

<uses-permission android:name="android.permission.BLUETOOTH" />

Ensuite , utilisez les filtres intention d'écouter la ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTEDet les ACTION_ACL_DISCONNECTEDémissions:

public void onCreate() {
    ...
    IntentFilter filter = new IntentFilter();
    filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
    this.registerReceiver(mReceiver, filter);
}

//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
           ... //Device found
        }
        else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
           ... //Device is now connected
        }
        else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
           ... //Done searching
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
           ... //Device is about to disconnect
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
           ... //Device has disconnected
        }           
    }
};

Quelques notes:

  • Il n'y a aucun moyen de récupérer une liste des appareils connectés au démarrage de l'application. L'API Bluetooth ne vous permet pas de QUERY, mais vous permet d'écouter les CHANGEMENTS.
  • Une solution difficile au problème ci-dessus serait de récupérer la liste de tous les appareils connus / appariés ... puis d'essayer de vous connecter à chacun (pour déterminer si vous êtes connecté).
  • Vous pouvez également demander à un service d'arrière-plan de surveiller l'API Bluetooth et d'écrire les états de l'appareil sur le disque pour que votre application les utilise ultérieurement.
Skylar Sutton
la source
2
C'est bon tant que mon application est en cours d'exécution, mais comment puis-je obtenir une liste à jour?
dchappelle
2
Comment prévoyez-vous d'exécuter du code sans que votre application ne «tourne»? Si vous voulez dire que vous devez y accéder à partir de quelque chose d'autre qu'une activité ... google Android Services, créez-en un pour écouter les émissions et conservez-le dans une liste.
Skylar Sutton
6
Je peux écouter les intentions MAIS comment puis-je obtenir la liste initiale des appareils Bluetooth connectés? Si l'un d'entre eux est déjà connecté au démarrage de mon activité ou de mon service, je ne le saurai pas. J'imagine (espère) que ces données sont disponibles quelque part? Je ne voudrais pas avoir à créer un service (qui fonctionne constamment tant que le téléphone est allumé) juste pour écouter ces intentions.
dchappelle
11
Il n'existe aucun moyen de récupérer la liste des appareils connectés au démarrage de l'application. L'API Bluetooth vous permettra uniquement d'écouter les changements de connexion. Alors oui, la seule façon de le faire est de créer un service de longue durée et d'ajouter / de supprimer une liste publique. C'est une grosse plainte de beaucoup de développeurs. En fonction de vos besoins en matière de performances, vous pouvez récupérer la liste des appareils couplés et essayer de vous connecter à chacun d'eux. S'il échoue, il n'est pas disponible. Un mot d'avertissement cependant: .connect () est une opération bloquante.
Skylar Sutton
1
@skylarsutton +1 Merci beaucoup pour cette réponse, m'a aidé à démarrer sur le bluetooth
AgentKnopf
33

Dans mon cas d'utilisation, je voulais uniquement voir si un casque Bluetooth est connecté pour une application VoIP. La solution suivante a fonctionné pour moi:

public static boolean isBluetoothHeadsetConnected() {
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
            && mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED;
} 

Bien sûr, vous aurez besoin de l'autorisation Bluetooth:

<uses-permission android:name="android.permission.BLUETOOTH" />

Jobbert
la source
2
C'est celui que je cherchais. Juste pour vérifier au lancement que le Bluetooth est connecté ou non. Merci, cela a fonctionné!
sud007
11

Un grand merci à Skylarsutton pour sa réponse. Je poste ceci en réponse à la sienne, mais comme je poste du code, je ne peux pas répondre en tant que commentaire. J'ai déjà voté pour sa réponse, donc je ne recherche aucun point. Juste payer en avant.

Pour une raison quelconque, BluetoothAdapter.ACTION_ACL_CONNECTED n'a pas pu être résolu par Android Studio. Peut-être était-il obsolète dans Android 4.2.2? Voici une modification de son code. Le code d'enregistrement est le même; le code du récepteur diffère légèrement. J'utilise ceci dans un service qui met à jour un drapeau connecté Bluetooth que d'autres parties de l'application font référence.

    public void onCreate() {
        //...
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        this.registerReceiver(BTReceiver, filter);
    }

    //The BroadcastReceiver that listens for bluetooth broadcasts
    private final BroadcastReceiver BTReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
            //Do something if connected
            Toast.makeText(getApplicationContext(), "BT Connected", Toast.LENGTH_SHORT).show();
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
            //Do something if disconnected
            Toast.makeText(getApplicationContext(), "BT Disconnected", Toast.LENGTH_SHORT).show();
        }
        //else if...
    }
};
pmont
la source
1
votre code est correct; il n'était pas obsolète dans 4.2.2. La classe BluetoothAdapter ne contient pas ACTION_ACL_CONNECTED. Cette chaîne est dans la classe BluetoothDevice.
RobLabs
Merci d'avoir clarifié cela!
pmont
4

Il existe une fonction isConnected dans l'API système BluetoothDevice dans https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java

Si vous voulez savoir si un appareil limité (couplé) est actuellement connecté ou non, la fonction suivante fonctionne bien pour moi:

public static boolean isConnected(BluetoothDevice device) {
    try {
        Method m = device.getClass().getMethod("isConnected", (Class[]) null);
        boolean connected = (boolean) m.invoke(device, (Object[]) null);
        return connected;
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
}
LW
la source
Avez-vous vu cela donner un résultat différent de simplement vérifier si bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED?
Gumby The Green
D'après ce que je peux dire, ils donnent le même résultat. Notez que pour les utilisateurs de Kotlin, ces deux premières lignes sont juste val m: Method = device.javaClass.getMethod("isConnected")et val connected = m.invoke(device).
Gumby The Green
Merci, exactement ce dont j'avais besoin! C'est l'équivalent kotlin de cette méthode:fun isConnected(device: BluetoothDevice): Boolean { return try { val m: Method = device.javaClass.getMethod( "isConnected" ) m.invoke(device) as Boolean } catch (e: Exception) { throw IllegalStateException(e) } }
Takeya le
1

Ce code est pour les profils de casque, il fonctionnera probablement aussi pour d'autres profils. Vous devez d'abord fournir un écouteur de profil (code Kotlin):

private val mProfileListener = object : BluetoothProfile.ServiceListener {
    override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
        if (profile == BluetoothProfile.HEADSET) 
            mBluetoothHeadset = proxy as BluetoothHeadset            
    }

    override fun onServiceDisconnected(profile: Int) {
        if (profile == BluetoothProfile.HEADSET) {
            mBluetoothHeadset = null
        }
    }
}

Ensuite, lors de la vérification du Bluetooth:

mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET)
if (!mBluetoothAdapter.isEnabled) {
    return Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
}

L'appel de onSeviceConnected prend un peu de temps. Après cela, vous pouvez obtenir la liste des écouteurs connectés à partir de:

mBluetoothHeadset!!.connectedDevices
user5902306
la source
0

BluetoothAdapter.getDefaultAdapter().isEnabled -> renvoie true lorsque le bluetooth est ouvert

val audioManager = this.getSystemService(Context.AUDIO_SERVICE) as AudioManager

audioManager.isBluetoothScoOn -> renvoie true lorsque l'appareil est connecté

ravid rinek
la source
0

Je cherchais vraiment un moyen de récupérer l'état de connexion d'un appareil, et non d'écouter les événements de connexion. Voici ce qui a fonctionné pour moi:

BluetoothManager bm = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bm.getConnectedDevices(BluetoothGatt.GATT);
int status = -1;

for (BluetoothDevice device : devices) {
  status = bm.getConnectionState(device, BLuetoothGatt.GATT);
  // compare status to:
  //   BluetoothProfile.STATE_CONNECTED
  //   BluetoothProfile.STATE_CONNECTING
  //   BluetoothProfile.STATE_DISCONNECTED
  //   BluetoothProfile.STATE_DISCONNECTING
}
connorbode
la source