Korzystając z BluetoothAdapter
, możesz znaleźć urządzenia Bluetooth na odległość, korzystając z funkcji wykrywania urządzeń lub za pomocą zapytania o listę sparowanych urządzeń.
Zanim spróbujesz znaleźć urządzenia Bluetooth, upewnij się, że masz odpowiednie uprawnienia Bluetooth i skonfigurowałeś/skonfigurowałaś aplikację pod kątem Bluetooth.
Wykrywanie urządzeń to procedura skanowania, która przeszukuje lokalną przestrzeń w poszukiwaniu urządzeń z Bluetooth i wymaga podania informacji o każdym z nich. Ten proces jest czasami nazywany odkrywaniem, sprawdzaniem lub skanowaniem. Urządzenie Bluetooth w pobliżu odpowiada na żądanie wykrywania tylko wtedy, gdy jest obecnie dostępne i akceptuje żądania informacji. Jeśli urządzenie jest możliwe do wykrycia, odpowiada na żądanie wykrywania, udostępniając pewne informacje, takie jak nazwa urządzenia, jego klasa i jego unikalny adres MAC. Korzystając z tych informacji, urządzenie wykonujące proces wykrywania może zainicjować połączenie z wykrytym urządzeniem.
Ponieważ urządzenia dostępne do wykrycia mogą ujawniać informacje o lokalizacji użytkownika, proces wykrywania urządzenia wymaga dostępu do lokalizacji. Jeśli aplikacja jest używana na urządzeniu z Androidem 8.0 (poziom interfejsu API 26) lub nowszym, rozważ użycie interfejsu Companion Device Manager API. Ten interfejs API umożliwia wykrywanie urządzeń w imieniu Twojej aplikacji, dzięki czemu nie musi ona prosić o dostęp do lokalizacji.
Po pierwszym nawiązaniu połączenia z urządzeniem zdalnym użytkownik automatycznie otrzyma prośbę o sparowanie. Po sparowaniu urządzenia podstawowe informacje o nim (np. nazwa, klasa i adres MAC) są zapisywane i można je odczytać za pomocą interfejsów Bluetooth. Korzystając z znanego adresu MAC urządzenia zdalnego, można w dowolnym momencie nawiązać z nim połączenie bez przeprowadzania procesu wykrywania, o ile urządzenie znajduje się w zasięgu.
Pamiętaj, że sparowanie i połączenie to 2 różne czynności:
- Parowanie oznacza, że 2 urządzenia są świadome wzajemnej obecności, mają wspólny klucz łączenia, który może służyć do uwierzytelniania, oraz mogą nawiązywać szyfrowane połączenia.
- Połączenie oznacza, że urządzenia obecnie udostępniają kanał RFCOMM i mogą przesyłać dane między sobą. Obecne interfejsy API Bluetooth wymagają sparowania urządzeń, zanim można nawiązać połączenie RFCOMM. Parowanie odbywa się automatycznie, gdy rozpoczniesz szyfrowane połączenie za pomocą interfejsów Bluetooth API.
W następnych sekcjach dowiesz się, jak znaleźć sparowane urządzenia oraz jak wykrywać nowe urządzenia za pomocą wykrywania urządzeń.
Zapytania o sparowane urządzenia
Przed wykrywaniem urządzeń warto sprawdzić zestaw sparowanych urządzeń, aby sprawdzić, czy wybrane urządzenie jest już znane. Aby to zrobić, zadzwoń pod numer getBondedDevices()
.
Zwraca zestaw obiektów BluetoothDevice
reprezentujących sparowane urządzenia. Możesz na przykład wysłać zapytanie do wszystkich sparowanych urządzeń i pobrać nazwę oraz adres MAC każdego z nich, jak pokazuje ten fragment kodu:
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
Aby nawiązać połączenie z urządzeniem Bluetooth, wystarczy adres MAC powiązany z obiektem BluetoothDevice
. Aby go pobrać, wywołaj funkcję getAddress()
. Więcej informacji o tworzeniu połączenia znajdziesz w artykule Łączenie urządzeń Bluetooth.
Wykrywanie urządzeń
Aby rozpocząć wyszukiwanie urządzeń, zadzwoń pod numer
startDiscovery()
.
Proces jest asynchroniczny i zwraca wartość logiczną wskazującą, czy wykrywanie zostało uruchomione. Proces wykrywania zwykle obejmuje skanowanie zapytania przez około 12 sekund, a następnie skanowanie strony każdego znalezionego urządzenia w celu pobrania jego nazwy Bluetooth.
Aby otrzymywać informacje o każdym wykrytym urządzeniu, aplikacja musi zarejestrować BroadcastReceiver
w intencji ACTION_FOUND
. System przekazuje ten zamiar do każdego urządzenia. Intencjonalnie zawiera pola dodatkowe EXTRA_DEVICE
i EXTRA_CLASS
, które z kolei zawierają odpowiednio pola BluetoothDevice
i BluetoothClass
.
Ten fragment kodu pokazuje, jak zarejestrować się, aby obsługiwać transmisję po wykryciu urządzeń:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
Aby nawiązać połączenie z urządzeniem Bluetooth, wywołujesz funkcję getAddress()
na BluetoothDevice
, aby pobrać powiązany adres MAC.
Włączanie możliwości znalezienia
Aby umożliwić innym urządzeniom wykrycie lokalnego urządzenia, wywołaj interfejs startActivityForResult(Intent, int)
z zadaniem ACTION_REQUEST_DISCOVERABLE
. W ten sposób wysyła prośbę o włączenie trybu znajdowania systemu bez konieczności przechodzenia do aplikacji Ustawienia, co spowodowałoby zatrzymanie Twojej aplikacji. Domyślnie urządzenie staje się wykrywalne przez 2 minuty. Możesz zdefiniować inny czas trwania, do 5 minut, dodając parametr EXTRA_DISCOVERABLE_DURATION
.
Ten fragment kodu powoduje, że urządzenie jest wykrywalne przez 5 minut:
Kotlin
val requestCode = 1; val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivityForResult(discoverableIntent, requestCode)
Java
int requestCode = 1; Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(discoverableIntent, requestCode);
Ilustracja 2. Okno umożliwiające zwiększenie wykrywalności.
Wyświetla się okno z prośbą o pozwolenie na udostępnienie urządzenia, jak pokazano na rysunku 2. Jeśli użytkownik odpowie „Zezwól”, urządzenie będzie widoczne przez określony czas. Twoja aktywność otrzymuje wtedy wywołanie funkcji onActivityResult()
z kodem wyniku równym czasowi trwania okresu, w którym urządzenie było możliwe do wykrycia. Jeśli użytkownik odpowiedział „Odmów” lub wystąpił błąd, kod wyniku to RESULT_CANCELED
.
Urządzenie pozostaje w trybie wykrywania przez cały przydzielony czas. Aby otrzymywać powiadomienia o zmianie trybu wykrywalności, zarejestruj BroadcastReceiver
dla inencji ACTION_SCAN_MODE_CHANGED
. Ta intencja zawiera dodatkowe pola EXTRA_SCAN_MODE
i EXTRA_PREVIOUS_SCAN_MODE
, które odpowiadają odpowiednio nowemu i staremu trybowi skanowania. Możliwe wartości dla każdego dodatkowego elementu:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- Urządzenie jest w trybie wykrywalności.
SCAN_MODE_CONNECTABLE
- Urządzenie nie jest w trybie wykrywalności, ale nadal może nawiązywać połączenia.
SCAN_MODE_NONE
- Urządzenie nie jest w trybie wykrywania i nie może odbierać połączeń.
Jeśli inicjujesz połączenie z urządzeniem zdalnym, nie musisz włączać funkcji znajdowania urządzenia. Włączenie możliwości wykrycia jest konieczne tylko wtedy, gdy chcesz, aby aplikacja hostowała gniazdo serwera, które akceptuje przychodzące połączenia, ponieważ urządzenia zdalne muszą mieć możliwość wykrywania innych urządzeń przed nawiązywaniem z nimi połączenia.