Pierwszym krokiem podczas interakcji z urządzeniem BLE jest nawiązanie z nim połączenia. Więcej
a zwłaszcza z serwerem GATT na urządzeniu. Łączenie z GATT
na urządzeniu BLE, użyj
connectGatt()
. Przyjmuje ona 3 parametry:
Context obiekt autoConnect (wartość logiczna)
wskazujący, czy automatycznie połączyć się z urządzeniem BLE, gdy tylko
) oraz odniesienie do
BluetoothGattCallback:
Kotlin
var bluetoothGatt: BluetoothGatt? = null ... bluetoothGatt = device.connectGatt(this, false, gattCallback)
Java
bluetoothGatt = device.connectGatt(this, false, gattCallback);
Łączy się z serwerem GATT hostowanym przez urządzenie BLE i zwraca
BluetoothGatt, czyli
za pomocą których możesz przeprowadzać operacje klienta w GATT. Rozmówca (aplikacja na Androida)
jest klient GATT.
Usługa BluetoothGattCallback jest używana do dostarczania klientowi wyników, takich jak:
stanu połączenia oraz innych operacji na kliencie GATT.
Konfigurowanie powiązanej usługi
W poniższym przykładzie aplikacja BLE udostępnia aktywność
(DeviceControlActivity) aby połączyć się z urządzeniami Bluetooth, wyświetlić dane z urządzenia,
oraz wyświetlać usługi i cechy GATT obsługiwane przez urządzenie. Siedziba
na dane wejściowe użytkownika, aktywność ta komunikuje się z
Service o nazwie BluetoothLeService, która
współpracuje z urządzeniem BLE przez interfejs BLE API. Komunikacja jest
wykonane przy użyciu powiązanej usługi, która umożliwia
działanie związane z łączeniem się z obiektem BluetoothLeService i wywoływaniem funkcji,
połączyć urządzenia. BluetoothLeService wymaga:
Implementacja Binder, która zapewnia dostęp do
i usługi związane z aktywnością.
Kotlin
class BluetoothLeService : Service() { private val binder = LocalBinder() override fun onBind(intent: Intent): IBinder? { return binder } inner class LocalBinder : Binder() { fun getService() : BluetoothLeService { return this@BluetoothLeService } } }
Java
class BluetoothLeService extends Service { private Binder binder = new LocalBinder(); @Nullable @Override public IBinder onBind(Intent intent) { return binder; } class LocalBinder extends Binder { public BluetoothLeService getService() { return BluetoothLeService.this; } } }
Działanie może uruchomić usługę za pomocą
bindService()
z wynikiem Intent, aby rozpocząć
usługa, ServiceConnection
wdrożenia, aby nasłuchiwać zdarzeń połączenia i rozłączenia, a także flaga
aby określić dodatkowe opcje połączenia.
Kotlin
class DeviceControlActivity : AppCompatActivity() { private var bluetoothService : BluetoothLeService? = null // Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> // call functions on service to check connection and connect to devices } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.gatt_services_characteristics) val gattServiceIntent = Intent(this, BluetoothLeService::class.java) bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE) } }
Java
class DeviceControlActivity extends AppCompatActivity { private BluetoothLeService bluetoothService; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { // call functions on service to check connection and connect to devices } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE); } }
Skonfiguruj adapter Bluetooth
Powiązanie z usługą wymaga dostępu do
BluetoothAdapter Powinna
Sprawdź, czy w urządzeniu jest dostępna przejściówka. Przeczytaj sekcję Konfiguracja
Bluetooth, by dowiedzieć się więcej
BluetoothAdapter. W poniższym przykładzie kod konfiguracji umieszcza się w
Funkcja initialize(), która zwraca wartość Boolean wskazującą powodzenie.
Kotlin
private const val TAG = "BluetoothLeService" class BluetoothLeService : Service() { private var bluetoothAdapter: BluetoothAdapter? = null fun initialize(): Boolean { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() if (bluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter.") return false } return true } ... }
Java
class BluetoothLeService extends Service { public static final String TAG = "BluetoothLeService"; private BluetoothAdapter bluetoothAdapter; public boolean initialize() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } return true; } ... }
Ta aktywność wywołuje tę funkcję w ramach implementacji ServiceConnection.
Obsługa wartości zwróconej przez funkcję initialize() zależy od
aplikacji. Możesz wyświetlić użytkownikowi komunikat o błędzie informujący, że
Obecne urządzenie nie obsługuje funkcji Bluetooth lub wyłącz żadne funkcje
które wymagają Bluetootha do działania. W poniższym przykładzie
Metoda finish() zostaje wywołana dla aktywności
aby przenieść użytkownika z powrotem na poprzedni ekran.
Kotlin
class DeviceControlActivity : AppCompatActivity() { // Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> if (!bluetooth.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth") finish() } // perform device connection } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } } ... }
Java
class DeviceControlsActivity extends AppCompatActivity { private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { if (!bluetoothService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } // perform device connection } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } }; ... }
Połącz się z urządzeniem
Po zainicjowaniu instancji BluetoothLeService może się ona połączyć z BLE
urządzenia. Aktywność musi wysłać adres urządzenia do usługi, aby mogła
zainicjuj połączenie. Usługa najpierw wywoła metodę
getRemoteDevice()
na urządzeniu BluetoothAdapter, aby uzyskać dostęp do urządzenia. Jeśli adapter nie może znaleźć
urządzenia z tym adresem, getRemoteDevice() przesyła
IllegalArgumentException
Kotlin
fun connect(address: String): Boolean { bluetoothAdapter?.let { adapter -> try { val device = adapter.getRemoteDevice(address) } catch (exception: IllegalArgumentException) { Log.w(TAG, "Device not found with provided address.") return false } // connect to the GATT server on the device } ?: run { Log.w(TAG, "BluetoothAdapter not initialized") return false } }
Java
public boolean connect(final String address) { if (bluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } try { final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); } catch (IllegalArgumentException exception) { Log.w(TAG, "Device not found with provided address."); return false; } // connect to the GATT server on the device }
Funkcja DeviceControlActivity wywołuje funkcję connect(), gdy usługa jest
zainicjowano. Aktywność musi być przekazywana w adresie urządzenia BLE. W
W tym przykładzie adres urządzenia jest przekazywany do aktywności jako intencja
dodatkowe.
Kotlin
// Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> if (!bluetooth.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth") finish() } // perform device connection bluetooth.connect(deviceAddress) } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } }
Java
private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { if (!bluetoothService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } // perform device connection bluetoothService.connect(deviceAddress); } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } };
Zadeklarowanie wywołania zwrotnego GATT
Gdy aktywność poinformuje usługę, z którym urządzeniem i usługą się połączyć
jeśli połączy się z urządzeniem, usługa musi połączyć się z serwerem GATT
urządzenie BLE. To połączenie wymaga BluetoothGattCallback, aby odbierać wiadomości
powiadomienia o stanie połączenia, wykrywanie usług, charakterystyka
odczyty i powiadomienia o charakterystycznych cechach.
Ten temat dotyczy powiadomień o stanie połączenia. Zobacz Przenoszenie BLE , aby dowiedzieć się, jak osiągnąć skuteczność wykrywanie usług, odczyty cech i charakterystyki żądań powiadomienia.
onConnectionStateChange()
jest wyzwalana po zmianie połączenia z serwerem GATT urządzenia.
W poniższym przykładzie wywołanie zwrotne jest zdefiniowane w klasie Service, więc
można używać z
BluetoothDevice raz
z inną usługą.
Kotlin
private val bluetoothGattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server } } }
Java
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server } } };
Połącz z usługą GATT
Po zadeklarowaniu obiektu BluetoothGattCallback usługa może używać parametru
obiekt BluetoothDevice z funkcji connect(), który ma zostać połączony z GATT.
usłudze dostępnej na urządzeniu.
connectGatt()
. Wymaga to obiektu Context i wartości logicznej autoConnect
flaga i BluetoothGattCallback. W tym przykładzie aplikacja jest bezpośrednio
nawiązywane jest połączenie z urządzeniem BLE, więc sygnał false jest przekazywany dla autoConnect.
Dodano także właściwość BluetoothGatt. Umożliwi to usłudze zamknięcie
, gdy nie jest
jest potrzebna dłużej.
Kotlin
class BluetoothLeService : Service() { ... private var bluetoothGatt: BluetoothGatt? = null ... fun connect(address: String): Boolean { bluetoothAdapter?.let { adapter -> try { val device = adapter.getRemoteDevice(address) // connect to the GATT server on the device bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback) return true } catch (exception: IllegalArgumentException) { Log.w(TAG, "Device not found with provided address. Unable to connect.") return false } } ?: run { Log.w(TAG, "BluetoothAdapter not initialized") return false } } }
Java
class BluetoothLeService extends Service { ... private BluetoothGatt bluetoothGatt; ... public boolean connect(final String address) { if (bluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } try { final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); // connect to the GATT server on the device bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback); return true; } catch (IllegalArgumentException exception) { Log.w(TAG, "Device not found with provided address. Unable to connect."); return false; } } }
Aktualne informacje o transmisjach
Gdy serwer łączy się z serwerem GATT lub się od niego rozłącza, musi powiadomić o tym działania nowego stanu. Istnieje kilka sposobów wykonania tej czynności. poniższy przykład wykorzystuje transmisje do wysłania informacji między usługą a aktywnością.
Usługa deklaruje funkcję rozgłaszającą nowy stan. Ta funkcja wykonuje
w ciągu działania, który jest przekazywany do obiektu Intent przed transmisją
do systemu.
Kotlin
private fun broadcastUpdate(action: String) { val intent = Intent(action) sendBroadcast(intent) }
Java
private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); }
Po włączeniu funkcji transmisji jest ona wykorzystywana w
BluetoothGattCallback, aby wysyłać informacje o stanie połączenia z
Serwer GATT. Deklarowane są stałe i bieżący stan połączenia usługi
w usłudze reprezentującej działania Intent.
Kotlin
class BluetoothLeService : Service() { private var connectionState = STATE_DISCONNECTED private val bluetoothGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server connectionState = STATE_CONNECTED broadcastUpdate(ACTION_GATT_CONNECTED) } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server connectionState = STATE_DISCONNECTED broadcastUpdate(ACTION_GATT_DISCONNECTED) } } } ... companion object { const val ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED" const val ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED" private const val STATE_DISCONNECTED = 0 private const val STATE_CONNECTED = 2 } }
Java
class BluetoothLeService extends Service { public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTED = 2; private int connectionState; ... private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server connectionState = STATE_CONNECTED; broadcastUpdate(ACTION_GATT_CONNECTED); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server connectionState = STATE_DISCONNECTED; broadcastUpdate(ACTION_GATT_DISCONNECTED); } } }; … }
Wykrywaj aktualizacje dotyczące aktywności
Gdy usługa przekaże aktualizacje połączenia, aktywność musi
wdrożyć element BroadcastReceiver.
Zarejestruj tego odbiorcę podczas konfigurowania aktywności i wyrejestruj go, gdy
Aktywność opuszcza ekran. Nasłuchując zdarzeń z usługi,
działanie może zaktualizować interfejs użytkownika na podstawie bieżącego
stanu połączenia z urządzeniem BLE.
Kotlin
class DeviceControlActivity : AppCompatActivity() { ... private val gattUpdateReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { when (intent.action) { BluetoothLeService.ACTION_GATT_CONNECTED -> { connected = true updateConnectionState(R.string.connected) } BluetoothLeService.ACTION_GATT_DISCONNECTED -> { connected = false updateConnectionState(R.string.disconnected) } } } } override fun onResume() { super.onResume() registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter()) if (bluetoothService != null) { val result = bluetoothService!!.connect(deviceAddress) Log.d(DeviceControlsActivity.TAG, "Connect request result=$result") } } override fun onPause() { super.onPause() unregisterReceiver(gattUpdateReceiver) } private fun makeGattUpdateIntentFilter(): IntentFilter? { return IntentFilter().apply { addAction(BluetoothLeService.ACTION_GATT_CONNECTED) addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED) } } }
Java
class DeviceControlsActivity extends AppCompatActivity { ... private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { connected = true; updateConnectionState(R.string.connected); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { connected = false; updateConnectionState(R.string.disconnected); } } }; @Override protected void onResume() { super.onResume(); registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter()); if (bluetoothService != null) { final boolean result = bluetoothService.connect(deviceAddress); Log.d(TAG, "Connect request result=" + result); } } @Override protected void onPause() { super.onPause(); unregisterReceiver(gattUpdateReceiver); } private static IntentFilter makeGattUpdateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); return intentFilter; } }
W sekcji Przenieś dane BLE:
BroadcastReceiver służy też do przekazywania wykrywania usług jako
a także dane charakterystyczne urządzenia.
Zamknij połączenie GATT
Ważnym krokiem podczas obsługi połączeń Bluetooth jest zamknięcie
gdy skończysz korzystać z internetu. Aby to zrobić, wywołaj close()
na obiekcie BluetoothGatt. W poniższym przykładzie usługa
zawiera odniesienie do elementu BluetoothGatt. Po usunięciu powiązania aktywności z
, połączenie zostaje zamknięte, aby uniknąć rozładowywania baterii urządzenia.
Kotlin
class BluetoothLeService : Service() { ... override fun onUnbind(intent: Intent?): Boolean { close() return super.onUnbind(intent) } private fun close() { bluetoothGatt?.let { gatt -> gatt.close() bluetoothGatt = null } } }
Java
class BluetoothLeService extends Service { ... @Override public boolean onUnbind(Intent intent) { close(); return super.onUnbind(intent); } private void close() { if (bluetoothGatt == null) { Return; } bluetoothGatt.close(); bluetoothGatt = null; } }