2016-12-22 3 views
1

Ich benutze modifizierte Google Bluetooth Chat Anwendung, um Client-Server Bluetooth RFCOMM Kommunikation zwischen zwei Android-Geräten (mit Android 5 und Android 6) fortzufahren.BluetoothSocket OutputStream.write() Problem

Es gibt einige Code meiner Client-Anwendung:

private class ConnectedThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final BufferedInputStream mmInStream; 
    private final BufferedOutputStream mmOutStream; 

    private ByteBuffer outputBuffer = null; 

    private int currentOperation = 0; 

    private byte currentMessageType = 0; 

    ConnectedThread(BluetoothSocket socket) { 
     Log.d(LOG_TAG, "create ConnectedThread: Insecure"); 
     mmSocket = socket; 
     BufferedInputStream tmpIn = null; 
     BufferedOutputStream tmpOut = null; 

     try { 
      tmpIn = new BufferedInputStream(socket.getInputStream()); 
      tmpOut = new BufferedOutputStream(socket.getOutputStream()); 
     } catch (IOException e) { 
      Log.e(LOG_TAG, "temp sockets not created", e); 
     } 

     mmInStream = tmpIn; 
     mmOutStream = tmpOut; 
     setState(STATE_CONNECTED); 
    } 
    public void run() { 
     Log.i(LOG_TAG, "BEGIN mConnectedThread"); 
     byte[] buffer; 
     ByteBuffer intBuf; 
     int tempInt; 

     while (mState == STATE_CONNECTED) { 
      try { 
       if(mmInStream.available()>8) { 
        Log.i(LOG_TAG, mmInStream.available() + " f"); 
        buffer = new byte[9]; 
        mmInStream.read(buffer, 0, 9); 

        intBuf = ByteBuffer.wrap(buffer); 
        Log.i(LOG_TAG, "NEW MESSAGE: "+intBuf.getInt()+" "+intBuf.get()+" "+intBuf.getInt()); 
        intBuf.rewind(); 

        tempInt = intBuf.getInt(); 
        Log.i(LOG_TAG, tempInt + " GET OP ID " + intBuf.capacity()); 

        currentMessageType = intBuf.get(); 
        Log.i(LOG_TAG, currentMessageType + " GET OP TYPE"); 

        // ... some more code 
       } 
      } 
      catch (IOException err) { 
       Log.e(LOG_TAG, "disconnected", err); 
       connectionLost(); 
       break; 
      } 
     } 
    } 
    void write(byte[] data) { 
     try { 
      Log.i(LOG_TAG, "WRITE NEW MESSAGE: "+data.length); 

      mmOutStream.write(data); 
      SystemClock.sleep(200); 

     } catch (IOException e) { 
      Log.e(LOG_TAG, "Exception during write", e); 
     } 
    } 
    void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { 
      Log.e(LOG_TAG, "close() of connect socket failed", e); 
     } 
    } 

Dieser Teil verwaltet die BluetoothSocket Lese-/Schreiboperationen.

Also, was ist das Problem? Wenn ich Daten mit der Größe < 10000 Bytes (Byte-Array) sende, geht alles normal. Aber dann versuche ich einige große große Daten zu senden (> 10000 Bytes) und diese Nachricht empfangen (mit LogCat):

12-22 12:53:49.849 28177-28177/com.lukanin.testappjava2 I/(BLUETOOTH): DATA LENGTH: 35722 OPT ID: 1 TYPE: 11 
12-22 12:53:49.849 28177-28177/com.lukanin.testappjava2 I/(BLUETOOTH): SEND DATA: 1 11 35722 
12-22 12:53:49.849 28177-28177/com.lukanin.testappjava2 I/(BLUETOOTH): WRITE NEW MESSAGE: 35731 

[ 12-22 12:53:49.849 21464:21536 D/   ] 
PORT_WriteDataCO: tx queue is full,tx.queue_size:10890,tx.queue.count:11,available:14941 

[ 12-22 12:53:49.959 21464:21536 D/   ] 
PORT_WriteDataCO: tx queue is full,tx.queue_size:10890,tx.queue.count:11,available:3061 

Ich denke, es ist eine Art von Outputüberlauf, aber ich kann nicht verstehen, wie man es repariert. Was soll ich tun, um eine solche Situation zu verhindern? Gibt es Methoden, um die AusgabeStream Schreibverfügbarkeit zu überprüfen?

P.S. Diese Situation ist relevant für Android 5 (auf Android 6 scheint alles normal zu sein).

+0

verstehe ich nicht, was das Problem ist genau das, aber sehen, ob ein mmOutStream hinzufügen. flush() nach dem Schreiben der Daten hilft. – pringi

+0

Durch das Logcat-Beispiel, das Sie geschrieben haben, kann ich das Problem nicht wahrnehmen. Kannst du das bitte besser erklären? – pringi

+0

Nein. Ich habe eine solche Lösung versucht. In diesem Fall erhalte ich nur einen der Fehler ** PORT_WriteDataCO: tx queue is full ... **. – trinarr

Antwort

0

Ich bin nicht sicher, ob dies helfen wird, aber versuchen, in Stücke zu schreiben:

private static funal int CHUNK_SIZE = 200; 

..... 

int currentIndex = 0; 
int size = data.length; 
while (currentIndex < size) { 
    int currentLength = Math.Min(size-currentIndex, CHUNK_SIZE); 
    memOutStream.write(data, currentIndex, currentLength); 
    currentIndex += currentLength; 
} 
+0

Es funktioniert perfekt mit kleinen Daten. Aber ich kann immer noch keine großen Byte-Arrays senden (der Überlauf existiert schließlich noch). – trinarr

0

In Android 5,

/* if we're over buffer high water mark, we're done */ 
     if ((p_port->tx.queue_size > PORT_TX_HIGH_WM) 
     || (p_port->tx.queue.count > PORT_TX_BUF_HIGH_WM)) 
     { 
      port_flow_control_user(p_port); 
      event |= PORT_EV_FC; 
      debug("tx queue is full,tx.queue_size:%d,tx.queue.count:%d,available:%d", 
        p_port->tx.queue_size, p_port->tx.queue.count, available); 
      break; 
     } 

Ich weiß nicht, die Werte für PORT_TX_HIGH_WM oder PORT_TX_BUF_HIGH_WM aber davon ausgehen, dass diese tx.queue_size ist mehr als die maximal Sie senden können.

Siehe https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.0.0_r3/stack/rfcomm/port_api.c

+0

Vielen Dank für Informationen. Vielleicht wissen Sie, ob es eine Möglichkeit gibt, die derzeit beschreibbare Kapazität von tx queue zu erhalten? – trinarr

+0

In Android weiß ich nicht. Nur gefunden, diesen Artikel zu erklären, wie MTU ist zu entdecken, aber das ist sehr niedrige Ebene: http://blog.csdn.net/wendell_gong/article/details/45060337 – pringi

+0

Ich habe festgestellt, dass PORT_TX_BUF_HIGH_WM = 4, aber PORT_TX_HIGH_WM ist komplex zu berechnen , aber es sollte nicht größer als 1691 sein. Dies sind Konstanten in Android-Code. Aber es hängt von Hardware-, Hersteller- und Android-Version ab. – pringi