GATT callback 선언
일단 서비스가 기기에 연결되면 BluetoothGattCallback을 통해 연결 상태에 대한 알림을 받는다. 서비스 회복, Characters read, Characters notifications
onConnectionStateChanged 메소드는 디바이스의 GATT 서버 연결이 변경되었을 때 호출된다. 서비스 클래스에 선언되어 bluetoothAdapter 와 함께 사용될 수 있다. (서비스와 연결된 이후에)
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이 선언되면, 서비스는 connect 함수로부터 BluetoothDevice 객체를 사용할 수 있다.
예제에서는 바로 BLE Device에 연결한다.
class BluetoothService 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;
}
}
}
Broadcast 업데이트
GATT 서버로부터 연결이나 실패 상황시, 액티비티에 데이터를 보낼 필요가 있다. 다양한 방법이 있으나 예제에서는 broadcast를 사용한다. Service to activity
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
BluetoothGattCallback에서 사용된다. GATT서버 연결 상태를 처리하기 위함이다.
class BluetoothService 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;p
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);
}
}
};
…
}
Broadcast를 받는 Activity에서는 BroadcastReceiver를 등록한다. 액티비티의 생명주기에 맞춰 register하고 release한다. 현재 BLE 연결 상태에 따라 UI를 변경할 수 있다. BoradcastReceiver는 서비스 회복이나 디바이스로부터 Characteristics 정보를 받을 때도 사용된다.
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;
}
}
GATT 연결 닫기
연결 작업이 끝나면 닫아라. 액티비티가 서비스로부터 unbound될 때, 배터리 고갈을 방지할 수 있다.
class BluetoothService extends Service {
...
@Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private void close() {
if (bluetoothGatt == null) {
Return;
}
bluetoothGatt.close();
bluetoothGatt = null;
}
}
BLE 데이터 보내기
일단 BLE GATT 서버와 연결하면, 어떤 서비스가 디바이스에서 가능한지 알아내는데 연결을 사용할 수 있다. (디바이스에 데이터를 요청, GATT 캐릭터 정보가 변경될 때, 알람을 요청 등)
서비스 찾기
GATT 서버를 연결했을 때 가장 먼저할 것은 서비스를 찾는 것이다. 이는 가능한 remote 디바이스에 대한 정보를 비롯하여 서비스 characteristics 그리고 descriptors 정보를 제공한다. 이 예제에서는 일단 서비스가 기기에 성공적으로 연결되면 discoverServices 함수가 BLE 디바이스에 정보를 요청한다. (BluetoothGattCallback의 onConnectionStarteChange 메소드로 지정된)
이 서비스는 onServiceDiscovered 메소드를 재정의할 필요가 있다. 가능한 서비스들에서 디바이스가 리포트 될 때 호출된다.
class BluetoothService extends Service {
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
...
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);
// Attempts to discover services after successful connection.
bluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// disconnected from the GATT Server
connectionState = STATE_DISCONNECTED;
broadcastUpdate(ACTION_GATT_DISCONNECTED);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
};
}
서비스는 broadcast를 사용하여 액티비티에 알린다. 일단 서비스가 찾아지면, 서비스는 getServices 메소드를 통해 보내진 데이터를 받을 수 있다.
class BluetoothService extends Service {
...
public List<BluetoothGattService> getSupportedGattServices() {
if (bluetoothGatt == null) return null;
return bluetoothGatt.getServices();
}
}
액티비티는 브로드캐스트 인텐트를 받을 때, 다음 처리를 한다.
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);
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
displayGattServices(bluetoothService.getSupportedGattServices());
}
}
};
}
'프로그래밍 > Android, iOS' 카테고리의 다른 글
[Android / iOS] Push Notification 기능 추가 (0) | 2023.09.22 |
---|---|
안드로이드 BLE 통신(공식문서 번역) 3 (0) | 2023.07.23 |
안드로이드 BLE 통신(공식문서 번역) 1 (0) | 2023.07.23 |
[Android] 사이닝 처리 하기 (0) | 2022.12.09 |
[Android] Resize Bitmap (0) | 2022.05.11 |
댓글