Как читать все байты вместе через Bluetooth? - PullRequest
11 голосов
/ 10 февраля 2012

У меня есть приложение, которое использует Bluetooth для получения некоторых данных (байтов) с другого устройства. все идет хорошо, но у меня есть небольшая проблема с получением байтов все вместе. После получения байтов я показываю их на тосте, чтобы проверить их. Когда другое устройство отправляет 10 байтов вместе (например: «ABCDEFGHIJ»), программа возьмет только первый байт «A» и покажет его на тосте, затем перейдет ко второй итерации и прочитает остальные 9 байтов и покажет « BCDEFGHIJ "на тосте. Вот мой код:

byte[] buffer = new byte[1024]; // Read 1K character at a time.
int bytes = 0; // Number of bytes.

while(true)
{
    try
    {
        // Read from the InputStream.
        bytes = bInStream.read(buffer);

        // Send the obtained bytes to the MainActivity.
        mainActivityHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
    }
    catch(IOException e)
    {
        connectionLost();
        break;
    }
}

В MainActivity у меня есть:

// The Handler that gets information back from the BluetoothManager.
private final Handler handler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        switch(msg.what)
        {
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;

                // construct a string from the valid bytes in the buffer.
                String readMessage = new String(readBuf, 0, msg.arg1);
                Toast.makeText(MainActivity.this, readMessage, Toast.LENGTH_SHORT).show();
                break;

            // ...
        }
    }
};

Как я могу получить все байты вместе?!

Ответы [ 6 ]

7 голосов
/ 10 февраля 2012

Ммм, скорее всего, виновник в том, как вы отправляете сообщения. Ваш прием не имеет проблем, он будет получать столько байтов (до 1024), сколько записано.

Если у вас нет контроля над тем, как отправляются сообщения, вы, вероятно, можете прочитать один байт за раз, а затем отправить вам сообщение-обработчик, когда вы нажмете на предопределенный терминатор. Пример: "ABCDEFGHIJ #", где # - терминатор.

String msg = "";
byte ch;
while((ch=mInStream.read())!='#') {
    bytes++;
    msg+=ch;
}
5 голосов
/ 10 февраля 2012

Соединение Bluetooth является потоковым, а не пакетным. Нет гарантии или попытки сохранить пакетирование. Таким образом, любое количество записей может привести к любому количеству операций чтения, только поток байтов гарантированно будет правильным. Если вам нужно обнаружить пакеты, вам нужно предоставить свою собственную структуру пакетов, чтобы обернуть ваши данные. Например, добавьте поле длины перед каждым пакетом данных, чтобы можно было восстановить на принимающей стороне.

4 голосов
/ 29 ноября 2014

Принятый ответ от @broody правильный.Но если сами данные содержат '#', может быть сложно получить данные.Так что лучший подход, по моему мнению, это добавить '\ n', за которым следует '\ r' (или любые другие символы, которые вряд ли будут отображаться как данные См. Таблицу ASCII ) в устройстве, которое отправляет данные на ваш Androidприложение.Он просто действует как перевод строки и отмечает конец данных.

Например: ABCDEFGH \ n \ r

Тогда ваш код может выглядеть примерно так:

byte[] buffer = new byte[1024];
 while (true) {

         // Read from the InputStream
          buffer[bytes] = (byte) mmInStream.read();                 
         // Send the obtained bytes to the UI Activity
 if ((buffer[bytes] == '\n')||(buffer[bytes]=='\r'))
 {
   mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
   bytes=0;
 }
 else
 bytes++;
}

HopeЭто помогает С уважением

1 голос
/ 02 апреля 2018

Чтобы прочитать все байты вместе, вам нужно разделить данные на "\ n" или "\ r" или "\ r \ n" в вашем коде.

Например: если вы хотите отправить данные из Arduino в приложение Android через Bluetooth:

(код Arduino):

    int count =0;
    int sensorPin = 0;

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
    int val= analogRead(sensorPin);
      if(val<threshold){ 
         a++; 
      }
      else{
        delay(2);
        count = count + 1;
        Serial.print(count);
        Serial.print("\n");
          }

А теперь, чтобы прочитать отправленные данные (значение переменной 'count'), вот код Android Studio:

 private class ConnectedThread extends Thread {
        private final InputStream mmInStream;

        public ConnectedThread(BluetoothSocket socket) {
            InputStream tmpIn = null;

            // Get the input streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream(); // opens the input stream in order to retrieve InputStream objects
            } catch (IOException e) {
            }

            mmInStream = tmpIn;
        }

     public void run() {
        int bytes; // bytes returned from read()
        int availableBytes = 0;

        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                availableBytes = mmInStream.available();
                if(availableBytes>0){
                    byte[] buffer = new byte[availableBytes];  // buffer store for the stream
                    // Read from InputStream
                    bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
                    if (bytes>0){
                        h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();     // Send to message queue Handler
                    }
                   }
                } catch (IOException e) {
                break;
                        }
        }
    }

И это: (в методе onCreate ()):

mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
// The Handler that gets information back
 h = new Handler() { // Handler-->used to communicate b/w UI & BG Thread
            public void handleMessage(android.os.Message msg) {
                switch (msg.what) {
                    case RECEIVE_MESSAGE:// if receive message
                        byte[] readBuf = (byte[]) msg.obj;
                       String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array

                        sb.append(strIncom);                                                // append string
                        int endOfLineIndex = sb.indexOf("\n");                            // determine the end-of-line
                        if (endOfLineIndex > 0) {                                            // if end-of-line,
                            String sbprint = sb.substring(0, endOfLineIndex);               // extract string
                            sb.delete(0, sb.length());// and clear
                            Toast.makeText(ledControl.this,sbprint,Toast.LENGTH_SHORT).show();
                            footSteps.setText(sbprint);            // update TextView
                        }
                        break;
                }}};
0 голосов
/ 17 октября 2018

Ни один из приведенных выше ответов не работал для меня.Thread.sleep (1000) дал мне решение

0 голосов
/ 20 мая 2014

Способ обработки сообщений длиннее буфера (может быть опасно, потому что может занять вашу память, если никогда не очищается) - это обрабатывать их порциями:

String inString = "";
byte[] buffer = new byte[1024];  // buffer store for the stream
int bytes; // bytes returned from read()

while (true) {
    try {
        bytes = mmInStream.read(buffer);
        String chunk = new String(buffer, 0, bytes);
        if(chunk.contains(";"))
        {
            inString += chunk.substring(0,chunk.indexOf(';'));
            Message msg = new Message();
            msg.obj  = inString;
            handler.sendMessage(msg);
            inString =  chunk.substring(chunk.indexOf(';'));
        }
        else
        {
            inString += chunk;
        }
    } catch (IOException e) {
        break;
    }
}
...