Android Story

[Android] Bluetooth BLE 연동 가이드

WhiteDuck 2021. 5. 4. 17:53

// 2021. 05.04 에 작성된 가이드입니다. 

// targetSdkVersion 30

// 참고 : 끝에 full source code 가 있습니다. 급하신 분은 내려서 보시기 바랍니다. 

 

 

Bluetooth BLE

Bluetooth BLE 은 Scan 시 다음과 같은 프로파일을 반환합니다. 어떤 디바이스인지 알 수 있게 함이죠. 

 

 

프로파일 안에는 여러가지 Sercvice와 Service의 Characteristic 으로 나뉘어져 있습니다. 

각각의 Charactaristic 은 Bluetooth 기기와의 주고 받을 수 있는 연결체가 됩니다.

이 Characteristic 을 통해서 정보를 정보를 가져올 것이니 기억해두기 바랍니다. 

 


안드로이드에서의 Bluetooth

안드로이드에서 블루투스 BLE 로부터 데이터를 받기 위해서는

 

1. Bluetooth 기능 ON

2. ACCESS_FINE_LOCATION 퍼미션

 

이 적용되어 있어야 합니다.

따라서 먼저 일단 AndroidManifst.xml 에 퍼미션을 적용시켜 봅시다. 

 

 

 

프로그래밍 단에서도 구현해야 하는 것.

알고 계시죠?? 먼저 그것을 구현하기 전에 Bluetooth 정보를 연동하는 클래스 먼저 살펴보고자 합니다. 

 

 


 Bluetooth 연동 순서

 

Bluetooth 를 켜는 것과 Bluetooth 권한을 받고 난 이후의 실제 연동과정 순서는 다음과 같습니다. 

 

1. Bluetooth Scanning 

2. Choose Device  

3. Bluetooth Connect (GATT)

4. Read/Notify Value

 

 

1. Bluetooth Scanning

블루투스는 연결할 수 있는 종류에 따라 페어링을 해야 하는 것과 BLE 만 되는 것, 둘 다 가능한 것으로 나뉘어여 있습니다. 우리가 보고 있는 것은 BLE 이니 다른 부분은 생략하겠습니다. 

 

 

 

보는 것과 같이 단순히 BluetoothAdapter를 통해서 스캔을 활성화하고 약 2 분간 stopScan을 할때까지 스캔을 지속합니다. 여기에서의 Callback은 다음과 같이 선언되어 있습니다. 

 

2. Choose Device

 

 

몇몇의 변수들은 디바이스 관리를 위해 선언되어 있지만, 그런 부분을 제외하고 본다면, 간단하게 검색된 디바이스가 있으면, onCheckModelListener를 통해서 사용자가 사용할 디바이스인지 체크하고 있습니다. 만약 적절한 디바이스라면 다시 onCheckModelListener를 통해서 스캔되었다고 알립니다. 사실 ScanFilter를 통해서도 특정 Device를 가져오는 것이 가능하지만, 저는 DeviceType에 따라서 모든 BLE의 정보를 수집하기 위해서 따로 선언해주었습니다. 

 

 

이렇게 Scan된 디바이스를 바로 연결해봅시다. 

 

3. Bluetooth Connect (GATT)

 

 

device.connectGatt 를 통해서 간단하게 연결 시킬수 있습니다. 여기에서의 gattCallback은 연결 상황에 따라서 Callback해주는 역할을 합니다. BluetoothGattCallback 에서 사용할 부분은 4군데로 다음 메서드를 오버라이드 합니다.

 

1) public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) 

2) public void onServicesDiscovered(BluetoothGatt gatt, int status) 

3) public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)

4) public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)

 

각각 연결 상태, 서비스 발견, 읽어들인 데이터, 알림이 오는 데이터를 전달합니다. 

 

 

연결되는 디바이스 중에서 연결에 실패한 것은 다시 연결할 수 있도록 처리해주고, 잘 연결된 디바이스는 서비스 정보를 알 수 있도록 조치합니다. 

 

 

 

그렇게 발견된 서비스에서 Read가 가능한 Characteristic와 Notify가 가능한 Characteristic를 찾아서 정보를 받을 수 있도록 설정합니다. 

 

 

4. Read/Notify Value

 

 

저는 리스너를 통해서 실제 데이터를 받았을 때 상위 객체에서 파싱 및 데이터를 처리할 수 있도록 활용했습니다. 

 

 

자, 이제 실제 사용을 해볼까요? 

앞서 정의했던 코드들은 BluetoothGuide에 모두 선언하여 사용하였으니, 보실때 주의바랍니다. 

 

 


 

블루투스 모듈 적용해보기 

 

 

보이듯이 정말 간단합니다!

먼저 리스너들을 선언해주고, 앞서 말했었던 Bluetooth On 과 퍼미션을 수락받습니다

 

물론 받는 과정도 있어야겠죠? 저는 간단하게 퍼미션을 처리하려고 TedPermission을 사용했습니다. 

 

 

 

위에 보이는 것은 퍼미션이 수락되었을 때, 스캔을 시작하는 코드, Bluetooth를 On 했을때 퍼미션을 받는 코드를 보여주고 있습니다. 자연스러운 흐름대로 라면 모두 onPermissionGranted 를 통해서 스캔을 시작할 수 있겠죠. 

 

 

마지막으로 실제 데이터를 뷰까지 적용되는 코드입니다!

 

 

앞서 설명했던 대로 해줬을 뿐 사실 특별한 내용은 없습니다. 

 

1. isChecked 에서는 맞는 DeviceType 인지를 반환해서 Scan 할 디바이스를 정합니다. 

2. scannedDevice 에서는 지정된 디바이스를 연결합니다. 

3. onValue 는 Notify에서 가져온 정보인데, 저는 샤오미의 온습도 센서를 연결했습니다. 그래서 그에 맞는 정보를 세팅했습니다. 

4. formatter 에서는 BluetoothGattCharacteristic 을 어떻게 적절히 요리해서 정보를 변환하고 있는지를 보여줍니다. 

 

제가 XiaomiSensor 를 어떻게 선언했는지만 보고 결과화면도 보도록 하겠습니다. 

 

 

 


Result 

 

 

이상으로 BLE 센서데이터를 Android 에서 가져오는 방법에 대해서 설명했습니다. 

Full code 는 다음과 같습니다. 

 

MainActivity.java

BluetoothGuide.java

XiaomiSensor.java

반응형