마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

BluetoothLeAdvertiser 를 이용한 Beacon 정보 송신 문제

0 추천

죄송합니다 로그인을 안하고 질문해서 로그인하고 다시 질문드립니다 ㅜㅜ 죄송합니다

 

안녕하세요 안드로이드를 이용해 beacon 리모콘을 만드려고 하는데요 아래 코드는 

PowerOn, PowerOff 버튼을 누르면 Service uuid가 5105 이고 데이터는 각각 0x01, 0x02 인 비콘 신호를 만들어 전송합니다.

 

전송 방식은 아래와 같습니다.

1. 앱을 이용해 ON,OFF 버튼을 누르면 sendCommand 메서드를 실행한다. on = 0x01 , off = 0x02 값을 보냅니다.

2. 넘겨받은 데이터를 가지고 AdvertisData 객체를 생성하고 startAdvertising 메서드를 이용해 비콘신호를 송신한다.

3. onStartSuccess 콜백 이벤트 함수가 호출되면 곧바로 advertising 을 stop 한다.

 

전송은 잘 됩니다.

하지만 아래와 같이 테스트를 진행하면

 

1. on 버튼을 눌러 0x01  Beacon 신호를 전송한다.

2. off 버튼을 눌러 0x02 beacon 신호를 전송한다.

3. on 버튼을 눌러 0x01 beacon 신호를 전송한다.

 

이와 같이 결과가 나옵니다.

 

1에서 0x01 beacon 신호를 전송하면 data 패킷에 아무런 데이터도 표시되지 않습니다. (Bluetooth LE Scanner 앱을 통해 확인)

2에서 off 버튼을 눌렀음에도 불구하고 이전 on 버튼을 눌렀을 때의 데이터인 0x01이 표시됨

3에서 on 버튼을 눌렀음에도 이전 off 버튼을 눌렀을 때의 데이터닌 0x02이 표시됨

 

결론

- 처음데이터가 flush 되지 않고 queue?? 등에 남아 있어 새로운 데이터가 송신되지 않고 이전에 송신되지 못한 데이터를 송신하는것 같습니다. (그래서 데이터가 밀리는 것같아요)

원인이 무엇을까요??

 

문제원인예상

- onStartSuccess 호출되고 바로 stop을 해서 문제가되는건지..

- 어딘가 딜레이를 줘야하는건지..

- 블루투스에 쌓여있는 데이터를 clear 해주어야하는지.. <= 관련함수는 찾아봤는데 나오지 않음..

 

public class DeviceControlActivity extends AppCompatActivity implements Constants {
    public final static String TAG = DeviceControlActivity.class.getName();
    public BluetoothManager mBluetoothManager;
    public BluetoothLeAdvertiser mBluetoothLeAdvertiser;
    public BluetoothAdapter bluetoothAdapter;
    public AdvertiseSettings settings;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        advertisingInit();
    }
    
    public void mOnClick(View v){
        switch (v.getId()){
            case R.id.powerOn :
                sendCommand(new byte[]{0x01});
                break;
            case R.id.powerOff:
                sendCommand(new byte[]{0x02});
                break;

        }
    }

    public void advertisingInit(){
        mBluetoothManager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
        bluetoothAdapter = mBluetoothManager.getAdapter();

        mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        if (mBluetoothLeAdvertiser == null) {
            Log.e(TAG, "Failed to create advertiser");
            return;
        }

        bluetoothAdapter.getDefaultAdapter().setName("SANGIL");
        settings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
                .setConnectable(false)
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
                .setTimeout(0)
                .build();
    }
    public ParcelUuid shortUUID(String s) {
        return ParcelUuid.fromString("0000" + s + "-0000-1000-8000-00805F9B34FB");
    }


    private void sendCommand(byte[] sendData) {

        StringBuilder sb= new StringBuilder();
        for(byte c : sendData){
            sb.append(String.format("%02X",c));
        }
        Log.e("BEACON SENT1","DATA : "+ sb.toString());

        AdvertiseData data = new AdvertiseData.Builder()
                .addServiceData(shortUUID("5105"),sendData)
                .setIncludeDeviceName(true)
                .build();
        Log.e("BEACON SENT2",data.toString());

        mBluetoothLeAdvertiser
                .startAdvertising(settings, data, mAdvertiseCallback);


    }

    private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.e(TAG, "LE Advertise Started.");
            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.e(TAG, "LE Advertise Failed: " + errorCode);
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mBluetoothLeAdvertiser!=null){
            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
        }
    }
}
Printf (1,380 포인트) 님이 2017년 9월 11일 질문
Printf님이 2017년 9월 11일 수정
휴대폰을 비콘 디바이스로 쓰는 것인가요? 그럼 Advertise가 맞겠지만,
비콘 디바이스가 따로 있으면, Connect를 하고 해당 Characteristics에 Write를 해야 합니다.
보통 휴대폰을 Advertiser로 쓰지 않고, Scanner로 씁니다만...
답글으르 늦게 봣습니다 죄송합니다
네 휴대폰이 Beacon 이 됩니다 ㅜㅜ
흠. 그렇게도 해 보긴 했지만, 아쉽지만, 통신까지는 못해 보았네요... 도움이 못되겠네요.
- 휴대폰을 비콘 pheriperal로 동작시키면, 타인이 저를 모니터링할 수 있기 때문에, 별로 좋은 방법은 아니라고 생각됩니다.
- 안드로이드 OS 버전도 5.0 이상으로 올라갑니다.
ㅜㅜ 결국 포기하고 connection 모드로 진행하게 되었네요 ㅜㅜ 감사합니다

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...