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