저희 회사에서 만든 ble 장치와 통신하는 앱을 만들고 있습니다. 통신은 발송용 캐릭터리스틱과 수신용 캐릭터 리스틱을 이용해서 수발신을 하고 있습니다.
발신은 발송할 데이터를 큐에 넣고 writeCharacteristc을 한 후, onCharacteristicWrite 콜백이 오면 결과에 따라서 큐의 다음 데이터를 발송하는 방식입니다. 수신은 onChracteristicChanged 콜백을 통해 받고 브로드캐스팅 합니다.
일반적인 짧은 양의 데이터는 수 발신이 모두 잘 되고 있습니다. 그런데.. 60KB파일을 전송하고자 하는데, 발송마다 20~30ms와 같은 딜레이를 주지 않으면 어느 순간 onChracteristicChanged이 발생하지 않습니다. writeCharacteristc이 initiate가 실패한것도 아니었습니다.
전송속도 문제떄문에 딜레이를 주고 싶지 않은데, 위와같은 현상이 발생하여 고민입니다. 구글링 열심히 해봤지만 비슷한 증상을 찾지 못했습니다. 아시는 분 도움 부탁드립니다.
-- 추가 --
베가 아이언 1 4.4.2, 갤럭시s3 4.3 갤럭시s3 4.4.4에서는 딜레이 0은 모두 실패
노트3 5.0은 딜레이 0도 잘되네요.
코드 첨부합니다.
쓰기 콜백 부분입니다. 안드로이드 콜백에서 이부분을 다시 호출하도록 했습니다.
/**
* onCharacteristicWrite 콜백에 따라 실패 또는 성공 처리 하고, 다음 스트림을 발송한다.
*
* @param isGattSuccess 발송 성공 여부
* @param wroteValue 발송 값
*/
protected void onCharacteristicWrite(boolean isGattSuccess, byte[] wroteValue) {
stopWriteCallbackTimer();
//Log.i("STREAM", "onCharacteristicWrite " + isGattSuccess);
MposInputStream stream = streamQueue.peek();
//notify send part result
int msg = (isGattSuccess ? MSG_SEND_PART_BYTES_SUCCESS : MSG_SEND_PART_BYTES_FAIL);
notifyMsg(msg, stream.getAid(), stream.getCommandCode(), wroteValue);
/*
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
//*/
if (isGattSuccess) {
if (stream.available() > 0) {
writeFromStream();
return;
} else {
// Log.i("STREAM", "all stream data sent stream.available() : " +stream.available());
// all stream data sent
streamQueue.poll();
stream.close();
tcs.setResult(true);
trySendingFromQueue();
notifyMsg(MSG_SEND_BYTES_SUCCESS, stream.getAid(), stream.getCommandCode(), null);
}
} else {
// Log.i("STREAM", "NOT GattSuccess stream.available() : " + stream.available());
tcs.setResult(false);
streamQueue.poll();
stream.close();
trySendingFromQueue();
notifyMsg(MSG_SEND_BYTES_FAIL, stream.getAid(), stream.getCommandCode(), null);
}
}
쓰기 부분입니다. 데이터는 큐에 있고, 큐에는 인풋스트림이 들어갑니다. 발송은 스트림에서 20바이트씩 읽어서 발송합니다.
/**
* 스트림으로 부터 데이터를 읽어 발송한다.
* @return true, if the write operation was initiated successfully
*/
protected boolean writeFromStream() {
//Log.i("STREAM", "writeFromStream stream" );
MposInputStream stream = streamQueue.peek();
if ( ct.isCancellationRequested() && stream.available() > 0 ) {
//cancel
Log.i(TAG, "CANCELED - " + stream.available());
tcs.setCancelled();
streamQueue.poll();
stream.close();
notifyMsg(MSG_SEND_CANCELED, stream.getAid(), stream.getCommandCode(), null);
trySendingFromQueue();
return false;
}
byte[] data = null;
try {
int count = stream.read(buffer);
if ( count < 0) return false;
data = buffer.length == count ? buffer : Arrays.copyOf(buffer, count);
} catch (IOException e) {
e.printStackTrace();
streamQueue.poll();
stream.close();
notifyMsg(MSG_SEND_PART_BYTES_FAIL, stream.getAid(), stream.getCommandCode(), data);
notifyMsg(MSG_SEND_BYTES_FAIL, stream.getAid(), stream.getCommandCode(), null);
trySendingFromQueue();
return false;
}
//scheduleWriteCallbackTimeout(stream, data);
boolean initiated = writeCharacteristic(data);
if ( !initiated ){
Log.v(TAG, "writeFromStream - initiated : " + initiated + " available : " + stream.available());
stopWriteCallbackTimer();
notifyMsg(MSG_SEND_PART_BYTES_FAIL, stream.getAid(), stream.getCommandCode(), data);
notifyMsg(MSG_SEND_BYTES_FAIL, stream.getAid(), stream.getCommandCode(), null);
trySendingFromQueue();
}
return initiated;
}