Jak programowo sprawdzić, czy urządzenie Bluetooth jest podłączone?

86

Rozumiem, jak uzyskać listę sparowanych urządzeń, ale jak mogę sprawdzić, czy są połączone?

Musi to być możliwe, ponieważ widzę je na liście urządzeń Bluetooth mojego telefonu i określa ich stan połączenia.

dchappelle
źródło

Odpowiedzi:

155

Dodaj uprawnienia Bluetooth do pliku AndroidManifest,

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

Następnie użyć filtrów zamiaru słuchać ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTEDi ACTION_ACL_DISCONNECTEDtransmisjach:

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

Kilka uwag:

  • Nie ma możliwości pobrania listy podłączonych urządzeń podczas uruchamiania aplikacji. Interfejs API Bluetooth nie pozwala na QUERY, zamiast tego umożliwia słuchanie CHANGES.
  • Drobnym obejściem powyższego problemu byłoby pobranie listy wszystkich znanych / sparowanych urządzeń ... a następnie próba połączenia się z każdym z nich (w celu ustalenia, czy masz połączenie).
  • Alternatywnie możesz mieć usługę działającą w tle, która będzie obserwować interfejs API Bluetooth i zapisywać stany urządzeń na dysku, aby aplikacja mogła ich użyć w późniejszym terminie.
Skylar Sutton
źródło
2
Jest to dobre, o ile moja aplikacja jest uruchomiona, ale jak mogę uzyskać aktualną listę?
dchappelle,
2
Jak planujesz wykonywać kod bez "uruchomionej" aplikacji? Jeśli masz na myśli, że chcesz uzyskać do tego dostęp z czegoś innego niż działanie ... przejdź do usług Google Android, utwórz jedną z nich, aby słuchać transmisji, i zachowaj ją na liście.
Skylar Sutton
6
Mogę nasłuchiwać intencji, ALE jak uzyskać wstępną listę podłączonych urządzeń Bluetooth? Jeśli któryś z nich jest już podłączony do czasu rozpoczęcia mojej aktywności lub usługi, nie będę wiedział. Wyobrażam sobie (mam nadzieję), że te dane są gdzieś dostępne? Nie chciałbym tworzyć usługi (która działa bez przerwy tak długo, jak telefon jest włączony) tylko po to, aby nasłuchiwać tych zamiarów.
dchappelle
11
Nie ma możliwości pobrania listy podłączonych urządzeń podczas uruchamiania aplikacji. Interfejs API Bluetooth pozwala tylko słuchać zmian połączenia. Więc tak, jedynym sposobem na to jest utworzenie długo działającej usługi i dodanie / usunięcie z listy publicznej. To duża skarga ze strony wielu programistów. W zależności od potrzeb w zakresie wydajności możesz pobrać listę sparowanych urządzeń i spróbować połączyć się z każdym z nich. Jeśli się nie powiedzie, jest niedostępny. Słowo ostrzeżenia: .connect () jest operacją blokującą.
Skylar Sutton,
1
@skylarsutton +1 Wielkie dzięki za tę odpowiedź, pomogło mi zacząć korzystać z bluetooth
AgentKnopf
33

W moim przypadku chciałem tylko sprawdzić, czy zestaw słuchawkowy Bluetooth jest podłączony do aplikacji VoIP. U mnie zadziałało następujące rozwiązanie:

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

Oczywiście będziesz potrzebować pozwolenia Bluetooth:

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

jobbert
źródło
2
To jest ten, którego szukałem. Wystarczy sprawdzić po uruchomieniu, czy Bluetooth jest podłączony, czy nie. Dzięki, zadziałało!
sud007
11

Wielkie dzięki dla Skylarsutton za odpowiedź. Wysyłam to jako odpowiedź na jego, ale ponieważ wysyłam kod, nie mogę odpowiedzieć jako komentarz. Głosowałem już za jego odpowiedzią, więc nie szukam żadnych punktów. Po prostu płacę dalej.

Z jakiegoś powodu BluetoothAdapter.ACTION_ACL_CONNECTED nie może zostać rozwiązany przez Android Studio. Być może został wycofany w systemie Android 4.2.2? Oto modyfikacja jego kodu. Kod rejestracyjny jest taki sam; kod odbiornika różni się nieznacznie. Używam tego w usłudze, która aktualizuje flagę połączenia Bluetooth, która odnosi się do innych części aplikacji.

    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
źródło
1
twój kod jest poprawny; nie był przestarzały w 4.2.2. Klasa BluetoothAdapter nie zawiera ACTION_ACL_CONNECTED. Ten ciąg znajduje się w klasie BluetoothDevice.
RobLabs
Dziękuję za wyjaśnienie!
pmont
4

Jest isconnected funkcja w BluetoothDevice systemu API w https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java

Jeśli chcesz wiedzieć, czy powiązane (sparowane) urządzenie jest obecnie podłączone, czy nie, następująca funkcja działa dobrze dla mnie:

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
źródło
Czy widziałeś, że to daje inny wynik niż tylko sprawdzenie, czy bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED?
Gumby The Green
Z tego, co wiem, dają ten sam wynik. Zauważ, że dla użytkowników Kotlin te pierwsze dwie linie to po prostu val m: Method = device.javaClass.getMethod("isConnected")i val connected = m.invoke(device).
Gumby The Green
Dziękuję, dokładnie to, czego potrzebowałem! Oto odpowiednik kotlin dla tej metody: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

Ten kod jest przeznaczony dla profili zestawu słuchawkowego, prawdopodobnie będzie działać również dla innych profili. Najpierw musisz podać odbiornik profilu (kod 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
        }
    }
}

Następnie podczas sprawdzania bluetooth:

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

Wywołanie onSeviceConnected zajmuje trochę czasu. Następnie możesz uzyskać listę podłączonych urządzeń słuchawkowych z:

mBluetoothHeadset!!.connectedDevices
user5902306
źródło
0

BluetoothAdapter.getDefaultAdapter().isEnabled -> zwraca prawdę, gdy Bluetooth jest otwarty

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

audioManager.isBluetoothScoOn -> zwraca prawdę, gdy urządzenie jest podłączone

Ravid Rinek
źródło
0

Naprawdę szukałem sposobu, aby pobrać stan połączenia urządzenia, a nie słuchać zdarzeń połączenia. Oto, co zadziałało dla mnie:

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
źródło