Как программно определить, подключено ли устройство Bluetooth?

86

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

Это должно быть возможно, поскольку я вижу их в списке устройств Bluetooth моего телефона, и в нем указывается статус их подключения.

Dchappelle
источник

Ответы:

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
Как вы планируете выполнять код без "запущенного" приложения? Если вы имеете в виду, что вам нужно получить доступ к этому из чего-то другого, кроме Activity ... перейдите в Google Android Services, создайте один из них для прослушивания трансляций и сохраните его в списке.
Скайлар Саттон
6
Я могу прослушивать намерения, НО как я могу получить начальный список подключенных устройств Bluetooth? Если к моменту запуска моей деятельности или службы они уже подключены, я не узнаю. Могу представить (надеюсь) эти данные где-то доступны? Я бы не хотел создавать службу (которая работает постоянно, пока телефон включен) только для того, чтобы прислушиваться к этим намерениям.
dchappelle
11
Невозможно получить список подключенных устройств при запуске приложения. Bluetooth API позволит вам только прослушивать изменения подключения. Так что да, единственный способ сделать это - создать долго работающую службу и добавить / удалить ее в публичный список. Многие разработчики жалуются на это. В зависимости от ваших требований к производительности вы можете получить список сопряженных устройств и попытаться подключиться к каждому из них. В случае неудачи он недоступен. Однако слово предупреждения: .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

Большое спасибо Скайларсаттон за его ответ. Я отправляю это как ответ на его, но поскольку я публикую код, я не могу ответить как комментарий. Я уже поддержал его ответ, поэтому не ищу никаких очков. Просто платите вперед.

По какой-то причине 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...
    }
};
pmont
источник
1
ваш код правильный; он не был объявлен устаревшим в версии 4.2.2. Класс BluetoothAdapter не содержит ACTION_ACL_CONNECTED. Эта строка находится в классе BluetoothDevice.
RobLabs
Спасибо за разъяснения!
pmont
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);
    }
}
LW
источник
Вы видели, что это дает другой результат, чем просто проверка того, действительно ли 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
user5902306
источник
0

BluetoothAdapter.getDefaultAdapter().isEnabled -> возвращает истину, когда bluetooth открыт

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

audioManager.isBluetoothScoOn -> возвращает истину при подключении устройства

Равид Ринек
источник
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
}
Коннорбод
источник