2011-09-23 5 views
7

Ho lavorato a un'app bluetooth per Android per un po 'di tempo e ho appena scoperto questo problema. Quando preformo mySocket.connect(); nella mia classe di servizio bluetooth, occasionalmente blocca indefinitamente. Ho letto la documentazione per BluetoothSocket.close() e dice:Bluetooth su Android: i miei blocchi Socket.connect() per sempre e Socket.close non sblocca

Chiudere immediatamente questo socket e rilasciare tutte le risorse associate.

Le chiamate bloccate su questo socket in altri thread immediatamente generano un IOException.

Tuttavia, questo non sembra funzionare per me. Ecco il mio codice per impostare un timer e poi provare a connetterti.

//code for starting timer and connecting 
    MyRunnable runner = new MyRunnable(mySocket); 
    Thread countThread = new Thread(runner); 
    countThread.start(); 

    mySocket.connect(); 
    runner.setSocketConnected(); 


//code for MyRunnable 
    private class MyRunnable implements Runnable{ 
     private boolean didSocketConnect = false; 
     private boolean socketConnectFailed = false; 
     private BluetoothSocket socket; 

     public MyRunnable(BluetoothSocket socket){ 
      this.socket = socket; 
     } 

     public void run() { 
      long start = System.currentTimeMillis(); 
      while(ESTABLISH_TIMEOUT + start >= System.currentTimeMillis() && !didSocketConnect && !socketConnectFailed){ 

      } 
      if(!didSocketConnect && !socketConnectFailed){ 
       Log.v(TAG,"Reached Timeout and socket not open. Look for #"); 
       try { 
        socket.close(); 
        Log.v(TAG,"#THIS CALL SHOULD BE MADE AFTER REACHED TIMEOUT AND SOCKET NOT OPEN"); 
       } catch (IOException e) { 
        Log.v(TAG,"Closing the socket connection fail--", e); 
       } 
      }else{ 
       Log.v(TAG, "Connected or Failed Before Timeout Thread Hit"); 
      } 
     } 

     public void setSocketConnected(){ 
      didSocketConnect = true; 
     } 

     public void setSocketFailed(){ 
      socketConnectFailed= true; 
     } 
    } 

Quando chiamo stretti(), si blocca anche a tempo indeterminato e la connect() chiamata non genera un IOException, nonostante la documentazione BluetoothSocket.close(). Qual è il modo migliore per farlo funzionare in modo che connect() e close() non si blocchino indefinitamente?

NOTA: sto utilizzando Android 2.2 per questo progetto.

+1

Hai mai trovato la causa/soluzione a questo problema? Sto incontrando la stessa cosa, ma sto usando due thread, un thread connect e un altro che chiama close(). –

+0

Ho lo stesso problema qui. Le chiamate al Mainthread si chiudono e non ritornano mai, ma non sempre, a volte funziona, a volte non lo fa. – NikkyD

risposta

2

BluetoothSocket.connect() - Dal documentation:

tentativo di connessione a un dispositivo remoto. Questo metodo verrà bloccato fino a quando non viene stabilita una connessione o la connessione non riesce. Se questo metodo restituisce senza un'eccezione, questo socket è ora connesso.

Per la chiamata a BluetoothSocket.connect() per uscire dal blocco, è necessario effettuare la connessione. Questo è in base alla progettazione e ha senso se ci si pensa, ottenere l'indirizzo del dispositivo Bluetooth a cui ci si vuole connettere, chiamare .connect() e bloccare fino a quando non è connesso. Questo è il motivo per cui vuoi fili separati.

Per quanto si chiama .close(), se si risolvono i problemi con .connect(), .close() dovrebbe andare a posto.

Leggere this. Fondamentalmente dice che vuoi un thread separato chiamato "connect" (.connect()) e "connected" (InputStream.read()). In questo modo l'interfaccia utente non verrà bloccata.

Esempio (dal link precedente). ConnectThread avvia la connessione. ConnectedThread gestisce la connessione (legge/scrive dati, ecc ...).

private class ConnectThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final BluetoothDevice mmDevice; 

    public ConnectThread(BluetoothDevice device) { 
     // Use a temporary object that is later assigned to mmSocket, 
     // because mmSocket is final 
     BluetoothSocket tmp = null; 
     mmDevice = device; 

     // Get a BluetoothSocket to connect with the given BluetoothDevice 
     try { 
      // MY_UUID is the app's UUID string, also used by the server code 
      tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 
     } catch (IOException e) { } 
     mmSocket = tmp; 
    } 

    public void run() { 
     // Cancel discovery because it will slow down the connection 
     mBluetoothAdapter.cancelDiscovery(); 

     try { 
      // Connect the device through the socket. This will block 
      // until it succeeds or throws an exception 
      mmSocket.connect(); 
     } catch (IOException connectException) { 
      // Unable to connect; close the socket and get out 
      try { 
       mmSocket.close(); 
      } catch (IOException closeException) { } 
      return; 
     } 

     // Do work to manage the connection (in a separate thread) 
     manageConnectedSocket(mmSocket); 
    } 

    /** Will cancel an in-progress connection, and close the socket */ 
    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { } 
    } 
} 


private class ConnectedThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final InputStream mmInStream; 
    private final OutputStream mmOutStream; 

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

     // Get the input and output streams, using temp objects because 
     // member streams are final 
     try { 
      tmpIn = socket.getInputStream(); 
      tmpOut = socket.getOutputStream(); 
     } catch (IOException e) { } 

     mmInStream = tmpIn; 
     mmOutStream = tmpOut; 
    } 

    public void run() { 
     byte[] buffer = new byte[1024]; // buffer store for the stream 
     int bytes; // bytes returned from read() 

     // Keep listening to the InputStream until an exception occurs 
     while (true) { 
      try { 
       // Read from the InputStream 
       bytes = mmInStream.read(buffer); 
       // Send the obtained bytes to the UI Activity 
       mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) 
         .sendToTarget(); 
      } catch (IOException e) { 
       break; 
      } 
     } 
    } 

    /* Call this from the main Activity to send data to the remote device */ 
    public void write(byte[] bytes) { 
     try { 
      mmOutStream.write(bytes); 
     } catch (IOException e) { } 
    } 

    /* Call this from the main Activity to shutdown the connection */ 
    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { } 
    } 
}