안드로이드로 BLE(Bluetooth Low Energy) 개발을 하다보면 2대의 폰이 하나는 Peripheral(Slave) 모드로 다른 하나는 Central(Master) 모드로 동작하는 테스트 앱을 만들어야 할 때가 있다.
왜냐하면 Bluetooth Classic(혹은 Bluetooth Basic)과는 달리 BLE의 경우는 Peripheral 모드로 동작하는 기기가 없으면 Central에서 아무리 scan을 해 봐야 검색 자체가 되지 않기 때문이다.
참고로 스마트폰의 경우는 BLE로도 혹은 Bluetooth Classic으로 동작을 하는 '듀얼 모드'(혹은 Bluetooth Smart Ready)를 지원하기 때문에 이상의 작업 환경을 만드는 것이 가능하다.
또 참고로 BLE만을 지원하는 경우를 Bluetooth Smart 디바이스라고 하고 '싱글 모드'로 표현하기도 한다. 이 경우는 기존의 Bluetooth Classic 기기와는 호환되지 않는다.
여기서 BLE가 Peripheral 모드로 동작한다는 뜻은 다른 BLE 디바이스와 connection을 맺기 위해 advertising signal을 주기적으로 내보내는 역할을 하는 기기를 말하고 Central로 동작한다는 뜻은 다른 BLE가 내보내는 advertising signal를 주기적으로 스캔하는 디바이스를 말한다.
아무튼...
이렇게 Peripheral 모드로 동작하는 안드로이드 개발을 하다보면 아래 코드조각의 onStartFailure() 메소드에서 errorCode 1을 반환하는 경우를 만나게 된다.
AdvertiseCallback advertisingCallback = new AdvertiseCallback(){
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect){
Toast.makeText(getApplicationContext(), "Advertising 성공~ ", 1).show();
super.onStartSuccess(settingsInEffect);
}
@Override
public void onStartFailure(int errorCode){
Log.e("BLE #######", "Advertising onStartFailure: "+errorCode); //여기서 errorCode가 1을 반환하는 에러
//아래 Toast에서 errorCode가 1이 나오는데 API 문서를 보면
//ADVERTISE_FAILED_DATA_TOO_LARGE 에러라고 설명이 되어 있다.
//Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.
Toast.makeText(getApplicationContext(), "Advertising onStartFailure: "+errorCode, 1).show();
super.onStartFailure(errorCode);
}
};
이 경우는 안드로이드 API 문서의 아래 설명과 같이 advertising의 데이터 길이가 31bytes를 넘어서 발생하는 문제이다.
"Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes."
BLE Peripheral 기기가 내보내는 advertising signal의 길이는 31byte로 한정되어 있는데 코드상에서 설정한 이 데이터의 크기가 31byte를 넘어서 발행한 경우이다.
아래 코드 조각이 advertising 데이터를 설정하는 코드이다.
BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.setConnectable(false)
.build();
ParcelUuid pUuid = new ParcelUuid(UUID.fromString(getString(R.string.ble_uuid2)));
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.addServiceUuid(pUuid)
.addServiceData(pUuid, "Data".getBytes(Charset.forName("UTF-8")))
.build();
위의 AdvertiseData의 설정을 아래와 같이 수정해본다.
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
// .addServiceUuid(pUuid)
// .addServiceData(pUuid, "Data".getBytes(Charset.forName("UTF-8")))
.build();
UUID와 Service Data를 advertising signal 데이터에 포함시키지 않도록 주석처리했다.
이제 문제가 해결되었을 것이고 다른 BLE에서 본 소스를 실행한 BLE를 정상적으로 잘 스캐닝 및 검색을 할수 있을 것이다.