Использование OutputStream соединения Bluetooth в другом потоке мешает получению сообщений - PullRequest
0 голосов
/ 24 сентября 2019

Я следовал Руководству по Android для создания соединения Bluetooth.

Чтобы отделить вещи и сделать их независимыми, я решил перенести отправляющую часть BT в отдельный поток.Для этого я передаю «OutStream» BT-Socket в отдельный класс Thread.Моя проблема в том, что как только я запускаю эту ветку, входящие сообщения перестают быть хорошо окрашенными.

Но я не знаю почему, потому что я не использую эту ветку в данный момент.Он запущен, но в нем нет сообщений.

Это часть класса "ConnectedToDevice", который принимает сообщения.Я использую особый способ определения того, что мои Сообщения получены полностью.

public void run() {
    byte[] buffer = new byte[1024];
    int bytes;

    sendPW();
    int len = 0;

    Communication.getInstance().setFrequentSending(OVS_CONNECTION_IN_PROGRESS);
    Communication.getInstance().setSendingMessages(mmOutStream); //Passing the OutStream to the sending class.
    Communication.getInstance().setReceivingMessages(queueReceivingMsg);

    Communication.getInstance().startThreads(); //currently: only start sending thread.

    while (true) {
      try {
        bytes = this.mmInStream.read(buffer, len, buffer.length - len);
        len += bytes;

        if (len >= 3 && buffer[2] != -1) {
          len = 0;
          Log.d(TAG, "run: To Short?");
        } else if (len >= 5) {
          int dataLength = Integer
              .parseInt(String.format("%02X", buffer[3]) + String.format("%02X", buffer[4]), 16);
          if (len == 6 + dataLength) {
            queueReceivingMsg.add(buffer);
            Log.d(TAG, "run: Added to queue");
            len = 0;
          }
          Log.d("BSS", "dataLenght: " + Integer.toString(dataLength) + " len " + len);
        }
      } catch (IOException var5) {
        cancel();
        Communication.getInstance().interruptThreads();
        return;
      }
    }
  }

Важная часть отправки сообщения Класс

public static BlockingQueue<Obj_SendingMessage> sendingMessages = new LinkedBlockingQueue<>();

@Override
  public void run() {
    while (!isInterrupted()) {
      if (bGotResponse){
        try{
          sendingMessage = sendingMessages.take();
          send(sendingMessage.getsData());
          bGotResponse = false;
          lTime = System.currentTimeMillis();
        } catch (InterruptedException e){
          this.interrupt();
        }
      }

      if((System.currentTimeMillis()%500 == 0) && System.currentTimeMillis() <= lTime+1000){
        if(sendingMessage != null){
          send(sendingMessage.getsData());
        }
      } else {
        bGotResponse =true;
      }
    }
  }

//Where the outStream is used
private void write(int[] buffer) {
    try {
      for (int i : buffer) {
        this.mmOutputStream.write(buffer[i]);
      }
    } catch (IOException var3) {

    }
  }

Чтобы еще раз очистить, sendingMessages пустовсе время, но сообщения по-прежнему не принимаются правильно.

1 Ответ

1 голос
/ 25 сентября 2019

Вот предложение о том, как может выглядеть надежный код для чтения сообщений из потока.Код может обрабатывать частичные и множественные сообщения следующим образом:

  • Ожидание большего количества данных, если сообщение не завершено
  • Обработка первого сообщения и сохранение оставшихся данных, если данные для болеедоступно более одного сообщения
  • Поиск байта маркера 0xff и сохранение данных для следующего, возможно, действительного сообщения, если необходимо удалить недействительные данные

Во время написания этого кода I 'Мы заметили еще одну ошибку в коде.Если сообщение найдено, данные не копируются.Вместо этого буфер возвращается.Однако буфер и, следовательно, возвращаемое сообщение могут быть перезаписаны следующим сообщением до или во время обработки предыдущего.

Эта ошибка является более серьезной, чем плохое декодирование потоковых данных.

private byte[] buffer = new byte[1024];
private int numUnprocessedBytes = 0;

public void run() {
    ...
    while (true) {
        try {
            int numBytesRead = mmInStream.read(buffer, numUnprocessedBytes, buffer.length - numUnprocessedBytes);
            numUnprocessedBytes += numBytesRead;
            processBytes();
        } catch (IOException e) {
            ...
        }
    }
}

private void processBytes() {
    boolean tryAgain;
    do {
        tryAgain = processSingleMessage();
    } while (tryAgain);
}

private boolean processSingleMessage() {
    if (numUnprocessedBytes < 5)
        return false; // insufficient data to decode length

    if (buffer[2] != (byte)0xff)
        // marker byte missing; discard some data
        return discardInvalidData();

    int messageLength = (buffer[3] & 0xff) * 256 + (buffer[4] & 0xff);
    if (messageLength > buffer.length)
        // invalid message length; discard some data
        return discardInvalidData();

    if (messageLength > numUnprocessedBytes)
        return false; // incomplete message; wait for more data

    // complete message received; copy it and add it to the queue
    byte[] message = Arrays.copyOfRange(buffer, 0, messageLength);
    queueReceivingMsg.add(message);

    // move remaining data to the front of buffer
    if (numUnprocessedBytes > messageLength)
        System.arraycopy(buffer, messageLength, buffer, 0, numUnprocessedBytes - messageLength);
    numUnprocessedBytes -= messageLength;

    return numUnprocessedBytes >= 5;
}

private boolean discardInvalidData() {
    // find marker byte after index 2
    int index = indexOfByte(buffer, (byte)0xff, 3, numUnprocessedBytes);
    if (index >= 3) {
        // discard some data and move remaining bytes to the front of buffer
        System.arraycopy(buffer, index - 2, buffer, 0, numUnprocessedBytes - (index - 2));
        numUnprocessedBytes -= index - 2;
    } else {
        // discard all data
        numUnprocessedBytes = 0;
    }
    return numUnprocessedBytes >= 5;
}

static private  int indexOfByte(byte[] array, byte element, int start, int end) {
    for (int i = start; i < end; i++)
        if (array[i] == element)
            return i;

    return -1;
}
...