Як програмно визначити, чи підключено пристрій Bluetooth?


86

Я розумію, як отримати список спарених пристроїв, але як я можу зрозуміти, чи підключені вони?

Це має бути можливо, оскільки я бачу їх у списку в списку пристроїв Bluetooth мого телефону і в них зазначається стан їхнього з’єднання.

Відповіді:


155

Додайте дозвіл Bluetooth до свого AndroidManifest,

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

Потім з допомогою фільтрів намірів , щоб прослухати ACTION_ACL_CONNECTED, ACTION_ACL_DISCONNECT_REQUESTEDі ACTION_ACL_DISCONNECTEDмовлення:

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

Кілька приміток:

  • Неможливо отримати список підключених пристроїв під час запуску програми. API Bluetooth не дозволяє запитувати, натомість дозволяє слухати ЗМІНИ.
  • Безглуздим способом вирішити вищезазначену проблему було б отримання списку всіх відомих / парних пристроїв ... а потім спроба підключитися до кожного з них (щоб визначити, чи підключені ви).
  • Крім того, у вас може бути фонова служба, яка переглядає API Bluetooth і записує стан пристрою на диск, щоб ваша програма використовувалась пізніше.

2
Це добре, поки працює моя програма, але як я можу отримати поточний список?
dchappelle

2
Як ви плануєте виконувати код без "запуску" вашої програми? Якщо ви маєте на увазі, що вам потрібно отримати доступ до чогось іншого, крім "Діяльність" ... перейдіть до Google Android Services, створіть один із них, щоб слухати трансляції, і продовжуйте його додавати до списку.
Skylar Sutton

6
Я можу слухати наміри, АЛЕ як я можу отримати початковий список підключених пристроїв Bluetooth? Якщо якісь із них вже підключені до моменту запуску моєї діяльності чи служби, я не буду знати. Я б уявив (сподіваюся) ці дані десь є? Мені не хотілося б створювати послугу (яка працює постійно, доки телефон увімкнено), аби просто слухати ці наміри.
dchappelle

11
Неможливо отримати список підключених пристроїв під час запуску програми. API Bluetooth дозволяє лише прослуховувати зміни підключення. Так що так, єдиний спосіб це зробити - створити тривалу службу та додати / видалити у загальнодоступний список. Це велика скарга багатьох розробників. Залежно від ваших потреб у продуктивності ви можете отримати список спарених пристроїв і спробувати підключитися до кожного з них. Якщо це не вдається, це недоступно. Слово попередження: .connect () - це операція блокування.
Skylar Sutton

1
@skylarsutton +1 Дякую купу за цю відповідь, допоміг мені розпочати роботу з Bluetooth
AgentKnopf

33

У моєму випадку я хотів лише перевірити, чи підключена гарнітура Bluetooth для програми VoIP. У мене працювало таке рішення:

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

Звичайно, вам знадобиться дозвіл Bluetooth:

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


2
Це той, кого я шукав. Просто перевірити при запуску, чи Bluetooth підключений чи ні. Дякую, це спрацювало!
sud007

11

Велика подяка Skylarsutton за його відповідь. Я публікую це як відповідь на його, але оскільки я публікую код, я не можу відповісти як коментар. Я вже підтримав його відповідь, тому не шукаю жодних пунктів. Просто платять його вперед.

З якихось причин BluetoothAdapter.ACTION_ACL_CONNECTED не вдалося вирішити Android Studio. Можливо, це застаріло в Android 4.2.2? Ось модифікація його коду. Реєстраційний код однаковий; код приймача дещо відрізняється. Я використовую це в службі, яка оновлює прапор Bluetooth, підключений до інших частин посилання на програму.

    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
ваш код правильний; воно не було застарілим у 4.2.2. Клас BluetoothAdapter не містить ACTION_ACL_CONNECTED. Цей рядок є в класі BluetoothDevice.
RobLabs

Дякуємо, що це пояснили!
Пмонт

4

У системному API BluetoothDevice є функція isConnected на https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java

Якщо ви хочете знати, чи обмежений (спарений) пристрій наразі підключено чи ні, для мене чудово працює наступна функція:

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

Ви бачили, що це дає інший результат, ніж просто перевірка bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED?
Gumby The Green

З того, що я можу сказати, вони дають однаковий результат. Зверніть увагу, що для користувачів Kotlin ці перші два рядки - це просто val m: Method = device.javaClass.getMethod("isConnected")і val connected = m.invoke(device).
Gumby The Green

Дякую, саме те, що мені було потрібно! Це еквівалент котліна для цього методу: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) } }
Такея

1

Цей код призначений для профілів гарнітури, ймовірно, він буде працювати і для інших профілів. Спочатку потрібно надати прослуховувач профілю (код 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
        }
    }
}

Потім під час перевірки Bluetooth:

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

Потрібно трохи часу, поки не буде викликано onSeviceConnected. Після цього ви можете отримати список підключених пристроїв гарнітури з:

mBluetoothHeadset!!.connectedDevices

0

BluetoothAdapter.getDefaultAdapter().isEnabled -> повертає true, коли bluetooth відкрито

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

audioManager.isBluetoothScoOn -> повертає true, коли пристрій підключено


0

Я справді шукав спосіб отримати статус з'єднання пристрою, а не слухати події з'єднання. Ось, що мені вдалося:

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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.