BLE Characteristics 정보 읽기
일단 GATT 서버에 앱이 연결되어 서비스를 찾으면, attributes를 읽을 수 있다. 스니펫에서는 서버의 서비스들과 characters를 순회하고 UI에 띄운다.
public class DeviceControlActivity extends Activity {
...
// Demonstrates how to iterate through the supported GATT
// Services/Characteristics.
// In this sample, we populate the data structure that is bound to the
// ExpandableListView on the UI.
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().
getString(R.string.unknown_service);
String unknownCharaString = getResources().
getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData =
new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData =
new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.
lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic :
gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData =
new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid,
unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
...
}
...
}
GATT 서비스는 디바이스로부터 읽을 수 있는 Characteristics 리스트 정보를 제공한다. 데이터 쿼리를 위해 BluetoothGatt의 readCharacteristic 메소드를 호출한다. (읽기 원하는 bluetoothGattCharacteristic을 넘긴다.)
class BluetoothService extends Service {
...
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (bluetoothGatt == null) {
Log.w(TAG, "BluetoothGatt not initialized");
return;
}
bluetoothGatt.readCharacteristic(characteristic);
}
}
이 예제에서 서비스는 readCharacteristic 메소드를 호출하기 위해 함수를 구현한다. 이는 비동기콜이다. 결과는 BluetoothGattcallback의 onCharacteristicRead으로 보내진다.
class BluetoothService extends Service {
...
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
...
@Override
public void onCharacteristicRead(
BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status
) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
};
}
특정한 콜백이 트리거될 때, 적절한 broadcastUpdate 메소드를 호출하여 action을 넘긴다.
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data
// parsing is carried out as per profile specifications.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" +
stringBuilder.toString());
}
}
sendBroadcast(intent);
}
GATT 알림 받기
디바이스에서 특정 Characteristics이 변경될 때, 알림을 받도록 요청하는 것이 BLE 앱에서는 일반적이다. 예제에서는 서비스가 함수를 구현한다. (setCharacteristicNotificiation 메소드를 호출하기 위해)
class BluetoothService extends Service {
...
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,boolean enabled) {
if (bluetoothGatt == null) {
Log.w(TAG, "BluetoothGatt not initialized");
Return;
}
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
}
}
}
일단 캐릭터 처리를 위한 알림이 활성화되면 onCharacteristicChanged 콜백이 트리거된다. (remote 디바이스에서 그 characteristic 정보가 변경되는 경우)
class BluetoothService extends Service {
...
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
...
@Override
public void onCharacteristicChanged(
BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic
) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
}
'프로그래밍 > Android, iOS' 카테고리의 다른 글
[Android / iOS] 테스트 앱 배포 과정 (0) | 2023.10.07 |
---|---|
[Android / iOS] Push Notification 기능 추가 (0) | 2023.09.22 |
안드로이드 BLE 통신(공식문서 번역) 2 (0) | 2023.07.23 |
안드로이드 BLE 통신(공식문서 번역) 1 (0) | 2023.07.23 |
[Android] 사이닝 처리 하기 (0) | 2022.12.09 |
댓글