Wie kann ich programmgesteuert feststellen, ob ein Bluetooth-Gerät verbunden ist?

84

Ich verstehe, wie ich eine Liste der gekoppelten Geräte erhalte, aber wie kann ich feststellen, ob sie verbunden sind?

Dies muss möglich sein, da sie in der Bluetooth-Geräteliste meines Telefons aufgeführt sind und der Verbindungsstatus angegeben ist.

dchappelle
quelle

Antworten:

154

Fügen Sie Ihrem AndroidManifest eine Bluetooth-Berechtigung hinzu.

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

Dann nutzen Absicht Filter die hören ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTEDund ACTION_ACL_DISCONNECTEDSendungen:

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

Ein paar Anmerkungen:

  • Es gibt keine Möglichkeit, beim Start der Anwendung eine Liste der verbundenen Geräte abzurufen. Mit der Bluetooth-API können Sie keine Abfragen durchführen, sondern Änderungen ändern.
  • Eine schwierige Lösung für das oben genannte Problem wäre, die Liste aller bekannten / gekoppelten Geräte abzurufen ... und dann zu versuchen, eine Verbindung zu jedem herzustellen (um festzustellen, ob Sie verbunden sind).
  • Alternativ können Sie die Bluetooth-API von einem Hintergrunddienst überwachen lassen und die Gerätezustände auf die Festplatte schreiben, damit Ihre Anwendung sie zu einem späteren Zeitpunkt verwenden kann.
Skylar Sutton
quelle
2
Dies ist gut, solange meine Anwendung ausgeführt wird. Wie kann ich jedoch eine aktuelle Liste abrufen?
Dchappelle
2
Wie planen Sie die Ausführung von Code, ohne dass Ihre Anwendung "ausgeführt" wird? Wenn Sie meinen, dass Sie von einer anderen Stelle als einer Aktivität darauf zugreifen müssen ... gehen Sie zu Google Android Services, erstellen Sie eine davon, um die Sendungen anzuhören, und speichern Sie sie in einer Liste.
Skylar Sutton
6
Ich kann auf die Absichten hören, ABER wie kann ich die erste Liste der verbundenen Bluetooth-Geräte erhalten? Wenn zum Zeitpunkt des Starts meiner Aktivität oder meines Dienstes bereits eine Verbindung besteht, weiß ich es nicht. Ich würde mir vorstellen (hoffe), dass diese Daten irgendwo verfügbar sind? Ich möchte keinen Dienst erstellen müssen (der ständig ausgeführt wird, solange das Telefon eingeschaltet ist), nur um auf diese Absichten zu achten.
Dchappelle
11
Es gibt keine Möglichkeit, die Liste der verbundenen Geräte beim Start der Anwendung abzurufen. Mit der Bluetooth-API können Sie nur Verbindungsänderungen abhören. Ja, der einzige Weg, dies zu tun, besteht darin, einen lang laufenden Dienst zu erstellen und einer öffentlichen Liste hinzuzufügen / zu entfernen. Es ist eine große Beschwerde vieler Entwickler. Abhängig von Ihren Leistungsanforderungen können Sie die Liste der gekoppelten Geräte abrufen und versuchen, eine Verbindung zu jedem Gerät herzustellen. Wenn es fehlschlägt, ist es nicht verfügbar. Ein Wort der Warnung: .connect () ist eine blockierende Operation.
Skylar Sutton
1
@ Skylarsutton +1 Vielen Dank für diese Antwort, half mir den Einstieg in Bluetooth
AgentKnopf
32

In meinem Anwendungsfall wollte ich nur sehen, ob ein Bluetooth-Headset für eine VoIP-App verbunden ist. Die folgende Lösung hat bei mir funktioniert:

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

Natürlich benötigen Sie die Bluetooth-Berechtigung:

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

jobbert
quelle
2
Dies ist der, nach dem ich gesucht habe. Nur um beim Start zu überprüfen, ob Bluetooth verbunden ist oder nicht. Danke, es hat funktioniert!
Sud007
11

Vielen Dank an Skylarsutton für seine Antwort. Ich poste dies als Antwort auf seine, aber da ich Code poste, kann ich nicht als Kommentar antworten. Ich habe seine Antwort bereits positiv bewertet und suche daher keine Punkte. Einfach vorwärts zahlen.

Aus irgendeinem Grund konnte BluetoothAdapter.ACTION_ACL_CONNECTED von Android Studio nicht aufgelöst werden. Vielleicht war es in Android 4.2.2 veraltet? Hier ist eine Modifikation seines Codes. Der Registrierungscode ist der gleiche. Der Empfängercode unterscheidet sich geringfügig. Ich verwende dies in einem Dienst, der ein Bluetooth-verbundenes Flag aktualisiert, auf das andere Teile der App verweisen.

    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
quelle
1
Ihr Code ist korrekt. es wurde in 4.2.2 nicht veraltet. Die BluetoothAdapter-Klasse enthält nicht ACTION_ACL_CONNECTED. Diese Zeichenfolge befindet sich in der BluetoothDevice-Klasse.
RobLabs
Vielen Dank für die Klarstellung!
pmont
3

In der BluetoothDevice-System-API unter https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java gibt es eine isConnected- Funktion

Wenn Sie wissen möchten, ob ein begrenztes (gekoppeltes) Gerät derzeit angeschlossen ist oder nicht, funktioniert die folgende Funktion für mich einwandfrei:

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
quelle
Haben Sie gesehen, dass dies zu einem anderen Ergebnis führt als nur zu prüfen, ob bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED?
Gumby The Green
Soweit ich das beurteilen kann, liefern sie das gleiche Ergebnis. Beachten Sie, dass für Kotlin-Benutzer diese ersten beiden Zeilen nur val m: Method = device.javaClass.getMethod("isConnected")und sind val connected = m.invoke(device).
Gumby The Green
Danke, genau das, was ich brauchte! Dies ist das Kotlin-Äquivalent für diese Methode: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
1

Dieser Code gilt für die Headset-Profile. Wahrscheinlich funktioniert er auch für andere Profile. Zuerst müssen Sie den Profil-Listener (Kotlin-Code) bereitstellen:

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
        }
    }
}

Dann beim Überprüfen von Bluetooth:

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

Es dauert einige Zeit, bis onSeviceConnected aufgerufen wird. Danach erhalten Sie möglicherweise eine Liste der angeschlossenen Headset-Geräte von:

mBluetoothHeadset!!.connectedDevices
user5902306
quelle
0

BluetoothAdapter.getDefaultAdapter().isEnabled -> gibt true zurück, wenn Bluetooth geöffnet ist

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

audioManager.isBluetoothScoOn -> gibt true zurück, wenn das Gerät angeschlossen ist

ravid rinek
quelle
0

Ich habe wirklich nach einer Möglichkeit gesucht, den Verbindungsstatus eines Geräts abzurufen und keine Verbindungsereignisse abzuhören. Folgendes hat bei mir funktioniert:

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
quelle