2012-12-07 9 views
7

Si è verificato un problema con Bluetooth nella mia app. Sembra che dopo il 28 BluetoothSocket/BluetoothServerSockets siano state create tutte le porte. Le prese non devono essere aperte contemporaneamente, sono solo 28 prese da quando Bluetooth è stato abilitato.Android: Bluetooth non è riuscito a ottenere il numero di porta

Questo può essere riprodotto utilizzando l'esempio BluetoothChat fornito nello Android Samples. Basta aprire e chiudere l'app 15 volte (l'app crea 2 socket ogni volta). Il 15 tempo, sarà in crash e continuerà a crash fino a disattivare e quindi riattivare Bluetooth:

12-06 18:43:58.177: E/BluetoothSocket(18530): bindListen, fail to get port number, exception: java.io.IOException: read failed, socket might closed, read ret: -1 
12-06 18:43:58.193: E/BluetoothChatService(18530): Socket Type: Insecurelisten() failed 
12-06 18:43:58.193: E/BluetoothChatService(18530): java.io.IOException: Error: -1 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.bluetooth.BluetoothAdapter.createNewRfcommSocketAndRecord(BluetoothAdapter.java:1035) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.bluetooth.BluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(BluetoothAdapter.java:982) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at com.example.android.BluetoothChat.BluetoothChatService$AcceptThread.<init>(BluetoothChatService.java:280) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at com.example.android.BluetoothChat.BluetoothChatService.start(BluetoothChatService.java:119) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at com.example.android.BluetoothChat.BluetoothChat.onResume(BluetoothChat.java:131) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.Activity.performResume(Activity.java:5182) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread.access$600(ActivityThread.java:141) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.os.Handler.dispatchMessage(Handler.java:99) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.os.Looper.loop(Looper.java:137) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at android.app.ActivityThread.main(ActivityThread.java:5039) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at java.lang.reflect.Method.invokeNative(Native Method) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at java.lang.reflect.Method.invoke(Method.java:511) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
12-06 18:43:58.193: E/BluetoothChatService(18530): at dalvik.system.NativeStart.main(Native Method) 

Esiste un modo per liberare le porte dopo il socket viene chiuso?

risposta

6

Posso verificare questo comportamento sul dispositivo che ho qui; anche se il numero di volte richiesto per arrestarsi nello stesso modo varia a seconda del dispositivo (penso che siano necessarie 20-25 volte sul Galaxy Nexus con 4.2), quindi il numero disponibile di maniglie delle porte sembra variare. Posso anche fornire le informazioni che il problema non è una perdita di memoria nell'app di esempio (o nella tua app), poiché tutte le istanze di BluetoothSocket sono state rilasciate e chiuse da Dalvik. I passaggi elencati qui verificano solo il problema su BluetoothServerSocket, quindi non è chiaro se il problema è specificamente correlato a quello, anche se sembra improbabile.

Almeno sui miei dispositivi, non è possibile avviare nuovamente l'app fino a quando non si commuta lo stato dell'adattatore Bluetooth, quindi il problema è sicuramente nella gestione sottostante delle connessioni nello stack.

Vorrei presentare un errore con i passaggi da riprodurre qui http://b.android.com e sarei felice di revocarlo.

+1

Grazie per dare un'occhiata! Ho registrato un bug qui: [# 41110] (http://code.google.com/p/android/issues/detail?id=41110). Ci sono volute 15 volte per far crashare l'app sia sul mio Galaxy Nexus che sul mio Nexus 7 con 4.2.1. Il mio Nexus One non si è mai schiantato, quindi spero che sia solo un problema di JB. – mattprecious

0

Recentemente, ho dovuto approfondire l'idea di una soluzione per questo. L'aggiornamento di Android non era un'opzione.

Si scopre che se, invece di distruggere e ricreare mAcceptThread ogni volta che viene stabilita/interrotta una connessione, mantenere l'istanza originale e riutilizzarla. Questo riduce al minimo l'effetto del bug sulla tua app.

Dal file BluetoothChatService, nella funzione collegata(), non cancella mAcceptThread:

public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { 
... 
... 
... 
// Cancel the accept thread because we only want to connect to one device 
//(Rather stay listening so comment out the cancel line!!) 
//If necessary, use some other state to prevent a second connection. 
//DONT CANCEL: if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} 
... 
... 

Nella classe AcceptThread, modificare il ciclo nella run() funzione:

  // Listen to the server socket if we're not connected 
//OLD LOOP:   while (mState != STATE_CONNECTED) 
//(Rather use STATE_NONE so the loop will only stop when the service does) 
      while (mState != STATE_NONE) 

Potrebbero esserci altre cose da fare nel codice per implementare correttamente l'idea.

0

Per ri-collegare io uso in un gestore a tempo nel frammento:

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(MainActivity.mac); 
        // Attempt to connect to the device 
        mChatService.connect(device, true); 

per risolvere il problema "fallisce quando ri-collegamento per più di 28 volte" ho commentato ogni volta che il servizio riparte stessa quando la connessione perdere:

//BluetoothChatService.this.start(); 

anche i commentata tutte le parti in cui la presa chiude:

//socket.close(); 

//mmServerSocket.close(); 

//mmSocket.close(); 

//mSecureAcceptThread.cancel(); 

e ha aggiunto un rilevamento non nullo per il filo accettare e collegati non THEAD a fallire:

if(mAdapter != null) { 
         tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, 
           MY_UUID_SECURE); 
        }else{ 
         mAdapter = BluetoothAdapter.getDefaultAdapter(); 
         //mState = STATE_NONE; 
        } 

e

if(mmServerSocket != null) { 
         socket = mmServerSocket.accept(); 
        } 

Ancora ottengo gocce di connessione casuale, ma il servizio ri collega e tutto funziona.

Problemi correlati