Come stabilire a livello di codice se un dispositivo Bluetooth è connesso?


87

Capisco come ottenere un elenco di dispositivi accoppiati, ma come posso sapere se sono collegati?

Deve essere possibile poiché li vedo elencati nell'elenco dei dispositivi Bluetooth del mio telefono e indica il loro stato di connessione.

Risposte:


156

Aggiungi l'autorizzazione Bluetooth al tuo AndroidManifest,

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

Quindi utilizzare filtri intento ad ascoltare la ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTEDe ACTION_ACL_DISCONNECTEDle trasmissioni:

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

Alcune note:

  • Non è possibile recuperare un elenco di dispositivi collegati all'avvio dell'applicazione. L'API Bluetooth non ti consente di QUERY, invece ti permette di ascoltare CAMBIAMENTI.
  • Una soluzione improvvisa al problema di cui sopra sarebbe recuperare l'elenco di tutti i dispositivi noti / accoppiati ... quindi provare a connettersi a ciascuno (per determinare se sei connesso).
  • In alternativa, potresti avere un servizio in background che guarda l'API Bluetooth e scrive gli stati del dispositivo su disco per la tua applicazione da utilizzare in un secondo momento.

2
Questo va bene finché la mia applicazione è in esecuzione, ma come posso ottenere un elenco aggiornato?
dchappelle

2
Come pensate di eseguire il codice senza che la vostra applicazione "sia in esecuzione"? Se intendi che devi accedervi da qualcosa di diverso da un'attività ... vai su Google Android Services, creane uno per ascoltare le trasmissioni e persistilo in un elenco.
Skylar Sutton

6
Posso ascoltare gli intenti MA come posso ottenere l'elenco iniziale dei dispositivi Bluetooth collegati? Se qualcuno è già connesso nel momento in cui la mia attività o servizio è iniziata, non lo saprò. Immagino (spero) che questi dati siano disponibili da qualche parte? Non vorrei dover creare un servizio (che funziona costantemente finché il telefono è acceso) solo per ascoltare questi intenti.
dchappelle

11
Non è possibile recuperare l'elenco dei dispositivi collegati all'avvio dell'applicazione. L'API Bluetooth ti consentirà solo di ascoltare le modifiche alla connessione. Quindi sì, l'unico modo per farlo è creare un servizio di lunga durata e aggiungere / rimuovere da un elenco pubblico. È una grossa lamentela da parte di molti sviluppatori. A seconda delle tue esigenze di prestazioni potresti recuperare l'elenco dei dispositivi accoppiati e provare a connetterti a ciascuno di essi. Se fallisce, non è disponibile. Un avvertimento però: .connect () è un'operazione di blocco.
Skylar Sutton

1
@skylarsutton +1 Grazie mille per questa risposta, mi ha aiutato a iniziare con il bluetooth
AgentKnopf

34

Nel mio caso d'uso volevo solo vedere se un auricolare Bluetooth è connesso per un'app VoIP. La seguente soluzione ha funzionato per me:

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

Ovviamente avrai bisogno dell'autorizzazione Bluetooth:

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


2
Questo è quello che stavo cercando. Solo per verificare all'avvio che il Bluetooth sia connesso o meno. Grazie ha funzionato!
sud007

11

Grazie mille a Skylarsutton per la sua risposta. Sto postando questo come risposta al suo, ma poiché sto postando codice non posso rispondere come commento. Ho già votato positivamente la sua risposta, quindi non sto cercando punti. Solo pagandolo in avanti.

Per qualche motivo BluetoothAdapter.ACTION_ACL_CONNECTED non può essere risolto da Android Studio. Forse è stato deprecato in Android 4.2.2? Ecco una modifica del suo codice. Il codice di registrazione è lo stesso; il codice del ricevitore è leggermente diverso. Lo uso in un servizio che aggiorna un flag di connessione Bluetooth a cui fanno riferimento altre parti dell'app.

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

1
il tuo codice è corretto; non era deprecato in 4.2.2. La classe BluetoothAdapter non contiene ACTION_ACL_CONNECTED. Quella stringa è nella classe BluetoothDevice.
RobLabs

Grazie per averlo chiarito!
pmont

6

C'è una funzione isConnected nell'API del sistema BluetoothDevice in https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java

Se vuoi sapere se il dispositivo collegato (accoppiato) è attualmente connesso o meno, la seguente funzione funziona bene per me:

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

Hai visto questo dare un risultato diverso dal solo controllo se bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED?
Gumby The Green

Da quello che posso dire, danno lo stesso risultato. Nota che per gli utenti di Kotlin, quelle prime due righe sono solo val m: Method = device.javaClass.getMethod("isConnected")e val connected = m.invoke(device).
Gumby The Green

Grazie, esattamente quello di cui avevo bisogno! Questo è l'equivalente kotlin per questo metodo: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

(Classe []) null 👈 È fantastico!
linjiejun

1

Questo codice è per i profili delle cuffie, probabilmente funzionerà anche per altri profili. Per prima cosa devi fornire il listener del profilo (codice 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
        }
    }
}

Quindi durante il controllo del Bluetooth:

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

Ci vuole un po 'di tempo prima che venga chiamato onSeviceConnected. Successivamente è possibile ottenere l'elenco dei dispositivi auricolari collegati da:

mBluetoothHeadset!!.connectedDevices

0

BluetoothAdapter.getDefaultAdapter().isEnabled -> restituisce true quando il bluetooth è aperto

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

audioManager.isBluetoothScoOn -> restituisce true quando il dispositivo è connesso


0

Stavo davvero cercando un modo per recuperare lo stato di connessione di un dispositivo, non per ascoltare gli eventi di connessione. Ecco cosa ha funzionato per me:

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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.