BLE 기기와 상호작용하는 첫 번째 단계는 기기에 연결하는 것입니다. 더보기
특히 장치의 GATT 서버에 연결하는 것입니다. GATT에 연결하기
BLE 기기에 연결하려면
connectGatt()
드림
메서드를 사용하여 축소하도록 요청합니다. 이 메서드는
Context
객체, autoConnect
(불리언
연결되자마자 BLE 기기에 자동으로 연결할지 여부를 나타냅니다.
사용할 수 있게 됨) 및
BluetoothGattCallback
:
Kotlin
var bluetoothGatt: BluetoothGatt? = null ... bluetoothGatt = device.connectGatt(this, false, gattCallback)
자바
bluetoothGatt = device.connectGatt(this, false, gattCallback);
이것은 저전력 블루투스 장치가 호스팅하는 GATT 서버에 연결하고
BluetoothGatt
인스턴스:
GATT 클라이언트 작업을 수행하는 데 사용할 수 있습니다. 호출자 (Android 앱)
GATT 클라이언트입니다. 이
BluetoothGattCallback
는 다음과 같은 결과를 클라이언트에 전달하는 데 사용됩니다.
추가 GATT 클라이언트 작업이 포함됩니다.
바인드된 서비스 설정
다음 예에서 BLE 앱은
(DeviceControlActivity
)를 사용하여 블루투스 기기에 연결하고 기기 데이터를 표시합니다.
기기에서 지원하는 GATT 서비스와 특성을 표시합니다. 기반
이 활동은
Service
가 BluetoothLeService
를 호출했으며,
BLE API를 통해 BLE 기기와 상호작용합니다. 통신은
바인드된 서비스를 사용하여 수행되며, 이를 통해
BluetoothLeService
에 연결하고 함수를 호출하여
장치에 연결하는 것입니다. BluetoothLeService
에는
Binder
구현을 통해
서비스를 제공할 수 있습니다.
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 } } }
자바
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; } } }
활동은 다음을 사용하여 서비스를 시작할 수 있습니다.
bindService()
님,
Intent
를 전달하여
서비스, ServiceConnection
연결 및 연결 해제 이벤트를 수신 대기하는 구현 및 플래그
추가 연결 옵션을 지정합니다.
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) } }
자바
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); } }
BluetoothAdapter 설정
서비스가 바인드되면
BluetoothAdapter
또한
기기에서 어댑터를 사용할 수 있는지 확인합니다. 설정을 읽어보세요.
블루투스에서 자세한 내용을 확인하세요.
BluetoothAdapter
다음 예에서는 이 설정 코드를
성공을 나타내는 Boolean
값을 반환하는 initialize()
함수
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 } ... }
자바
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; } ... }
활동은 ServiceConnection
구현 내에서 이 함수를 호출합니다.
initialize()
함수에서 false 반환 값을 처리하는 방법은
애플리케이션입니다. 사용자에게 오류가 있다는 것을 알려주는 오류 메시지를
현재 기기가 Bluetooth 작업을 지원하지 않거나 기능을 비활성화합니다.
블루투스가 작동해야 합니다. 다음 예에서
finish()
는 활동에서 호출됩니다.
이전 화면으로 돌아가도록 합니다.
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 } } ... }
자바
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; } }; ... }
기기에 연결
BluetoothLeService
인스턴스가 초기화되면 BLE에 연결할 수 있습니다.
있습니다. 활동은 기기 주소를 서비스로 보내야
연결을 시작합니다. 서비스는
getRemoteDevice()
드림
BluetoothAdapter
에서 기기에 액세스합니다. 어댑터에서 네트워크 연결의
getRemoteDevice()
가 해당 주소를 발생시킵니다.
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 } }
자바
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 }
DeviceControlActivity
는 서비스가 다음과 같이 작동하면 이 connect()
함수를 호출합니다.
초기화됩니다. 활동은 BLE 기기의 주소를 전달해야 합니다. 포함
다음 예에서는 기기 주소가 인텐트로 활동에 전달됩니다.
추가.
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 } }
자바
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; } };
GATT 콜백 선언
활동이 서비스에 연결할 기기와 서비스를 알려준 후
장치에 연결되면 서비스는 장치의 GATT 서버에 접속해야
BLE 기기 이 연결에서는 BluetoothGattCallback
이(가) 있어야
연결 상태, 서비스 검색, 특성에 대한 알림
특성 알림을 제공합니다
이 주제에서는 연결 상태 알림에 중점을 둡니다. BLE 전송 자세히 알아보려면 서비스 검색, 특성 읽기, 요청 특성 있습니다.
이
onConnectionStateChange()
드림
함수는 기기의 GATT 서버에 대한 연결이 변경될 때 트리거됩니다.
다음 예에서 콜백은 Service
클래스에 정의되어 있으므로
는
BluetoothDevice
를
가상 머신 서비스가 그것에 연결됩니다
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 } } }
자바
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 } } };
GATT 서비스에 연결
BluetoothGattCallback
가 선언되면 서비스는
GATT에 연결하기 위한 connect()
함수의 BluetoothDevice
객체
할 수 있습니다.
이
connectGatt()
드림
함수가 사용됩니다. Context
객체, autoConnect
부울이 필요합니다.
플래그 및 BluetoothGattCallback
입니다. 이 예에서 앱은
BLE 기기에 연결되므로 autoConnect
에 false
가 전달됩니다.
BluetoothGatt
속성도 추가됩니다. 이렇게 하면 서비스가
연결로 연결된 상태가 아닌 경우
더 오래 걸릴 수 있습니다
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 } } }
자바
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; } } }
브로드캐스트 업데이트
서버가 GATT 서버에 연결하거나 연결을 끊을 때 새로운 상태의 활동. 여기에는 여러 가지 방법이 있습니다. 이 다음 예에서는 broadcasts를 사용하여 정보를 전달할 수 있습니다
서비스는 새 상태를 브로드캐스트하는 함수를 선언합니다. 이 함수는
브로드캐스트되기 전에 Intent
객체에 전달되는 작업 문자열
시스템에 전달합니다
Kotlin
private fun broadcastUpdate(action: String) { val intent = Intent(action) sendBroadcast(intent) }
자바
private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); }
브로드캐스트 기능이 배치되면
BluetoothGattCallback
: 연결 상태에 관한 정보를
GATT 서버입니다. 상수와 서비스의 현재 연결 상태가 선언됨
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 } }
자바
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); } } }; … }
활동의 업데이트 수신 대기
서비스가 연결 업데이트를 브로드캐스트하면 활동은 다음과 같이 해야 합니다.
BroadcastReceiver
를 구현합니다.
활동을 설정할 때 이 수신자를 등록하고
화면 밖으로 나가야 합니다. 서비스의 이벤트를 수신 대기하면
활동은 현재
연결 상태가 됩니다.
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) } } }
자바
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; } }
BLE 데이터 전송에서,
BroadcastReceiver
는 서비스 검색을 전달하는 데도 사용됩니다.
특성 데이터를 얻을 수 있습니다
GATT 연결 닫기
Bluetooth 연결을 다룰 때 중요한 한 가지 단계는
연결을 종료할 수 있습니다. 이렇게 하려면 close()
를 호출합니다.
함수(BluetoothGatt
객체) 다음 예에서 서비스는
BluetoothGatt
참조를 보유합니다. 활동이
서비스인 경우 기기 배터리가 소모되지 않도록 연결이 종료됩니다.
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; } }