2011-09-23 5 views
7

He estado trabajando en una aplicación bluetooth para Android por un tiempo y acabo de descubrir este problema. Cuando preformas mySocket.connect(); en mi clase de servicio bluetooth ocasionalmente bloquea de forma indefinida. Leí la documentación para BluetoothSocket.close() y dice lo siguiente:Bluetooth en Android: mi Socket.connect() Bloquea para siempre, y Socket.close no desbloquea

Cierre inmediatamente este conector y libere todos los recursos asociados.

Causa las llamadas bloqueadas en este socket en otros hilos para inmediatamente lanzar una IOException.

Sin embargo, esto no parece funcionar para mí. Aquí está mi código para configurar un temporizador y luego tratar de conectarme.

//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; 
     } 
    } 

Cuando llamo a close(), que también bloquea indefinidamente y el() llamada connect nunca tira una IOException, a pesar de la documentación BluetoothSocket.close(). ¿Cuál es la mejor manera de hacerlo funcionar para que connect() y close() no se bloqueen indefinidamente?

NOTA: Estoy usando Android 2.2 para este proyecto.

+1

¿Alguna vez encontró la causa/solución a este problema? Me encuentro con lo mismo, pero estoy usando dos hilos, un hilo de conexión y otro que se llama close(). –

+0

Tengo el mismo problema aquí. Mainthread llama cerca y nunca regresa, pero no siempre, a veces funciona, a veces no funciona. – NikkyD

Respuesta

2

BluetoothSocket.connect() - Desde el documentation: Intento

para conectarse a un dispositivo remoto. Este método se bloqueará hasta que se realice una conexión o la conexión falle. Si este método devuelve sin excepción, este socket ahora está conectado.

Para que su llamada a BluetoothSocket.connect() deje de bloquearse, necesita hacer la conexión. Esto es por diseño y tiene sentido si lo piensas, obtienes la dirección del dispositivo Bluetooth al que queremos conectarte, llamas a .connect() y bloqueas hasta que esté conectado. Es por eso que quieres hilos separados.

Por lo que usted llama a .close(), si resuelve los problemas con .connect(), .close() debería estar en su lugar.

Por favor, lea this. Básicamente dice que quiere un hilo separado llamado "conectar" (.connect()) y "conectado" (InputStream.read()). De esta forma, su IU no se bloqueará.

Ejemplo (desde el enlace de arriba). ConnectThread inicia la conexión. ConnectedThread gestiona la conexión (lee/escribe datos, etc.).

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) { } 
    } 
} 
Cuestiones relacionadas