2013-02-18 8 views
12

Sto eseguendo la compilazione di SDK 10 (2.3.3):Quando si annulla il socket del server bluetooth prima di accettare, l'intero processo muore. Perché?

android:minSdkVersion="10" 
android:targetSdkVersion="16" 

sto testando su due smartphone Sony Ericsson. Uno ha Android 2.3.7 su di esso e l'altro 4.0.1.

Sto usando listenUsingInsecureRfcommWithServiceRecord per aprire un nuovo socket server su bluetooth e ascoltare le connessioni.

Se la connessione viene accettata correttamente, tutto funziona correttamente. Posso anche provare a cancellare il socket del server, ma questo non sembra disturbare il socket di connessione appena creato.

MA quando voglio annullare la presa del server prima di aver accettato qualsiasi connessione non appena viene eseguita la riga bluetoothServerSocket.close(); l'intera attività si chiude e il processo muore. E inoltre questo è non un'eccezione regolare che potrei gestire.

In realtà anche lo stesso logcat si chiude !! e devo eseguire rapidamente di nuovo al fine di afferrare gli errori potete vedere qui sotto:

Zygote D Process 25471 terminated by signal (11) 
    295   InputDispatcher W channel '2c2e20a8 com.pligor.test/activities.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x8 
    295   InputDispatcher E channel '2c2e20a8 com.pligor.test/activities.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed! 
    295    dalvikvm D GC_FOR_ALLOC freed 1299K, 21% free 13252K/16583K, paused 93ms 
    295   InputDispatcher W Attempted to unregister already unregistered input channel '2c2e20a8 com.pligor.test/activities.MainActivity (server)' 
    295  BluetoothService D Tracked app 25471 diedType:10 
    295  BluetoothService D Removing service record 10009 for pid 25471 
    132   SurfaceFlinger D Release buffer at 0x61c08 
    295   WindowManager I WINDOW DIED Window{2c2e20a8 com.pligor.test/activities.MainActivity paused=false} 
    295   ActivityManager I Process com.pligor.test (pid 25471) has died. 
    295   ActivityManager W Force removing ActivityRecord{2c021800 com.pligor.test/activities.MainActivity}: app died, no saved state 
    295   WindowManager W Failed looking up window 
    295   WindowManager W java.lang.IllegalArgumentException: Requested window [email protected] does not exist 
    295   WindowManager W at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7165) 
    295   WindowManager W at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:7156) 
    295   WindowManager W at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1545) 
    295   WindowManager W at android.os.BinderProxy.sendDeathNotice(Binder.java:417) 
    295   WindowManager W at dalvik.system.NativeStart.run(Native Method) 
    295   WindowManager I WIN DEATH: null 
    295  BluetoothEventLoop D Property Changed: UUIDs : 11 
    295 hAdapterStateMachine D BluetoothOn process message: 51 
    295  InputManagerService W Got RemoteException sending setActive(false) notification to pid 25471 uid 10040 

Nota: Processo terminato dal segnale (11) significa Segmentation fault (http://en.wikipedia.org/wiki/SIGSEGV).

EDIT

ho creare il socket server di Bluetooth utilizzando il seguente codice (Scala):

private val bluetoothServerSocket: BluetoothServerSocket = try { 
    bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(MY_SERVICE_NAME_INSE‌​CURE, MY_UUID_INSECURE); 
} 
catch { 
    case e: IOException => throw new ServerSocketException; 
} 

Io uso questo codice per chiudere la Bluetooth presa:

try { 
    isCancelled = true; 
    bluetoothServerSocket.close(); 
} catch { 
    case e: IOException => throw new NotClosedException; 
} 
+0

Ho fatto una piccola ricerca, e sembra che le interruzioni del segnale (11) siano causate da programmi che accedono alla memoria a cui non dovrebbero accedere o che non esistono. Non so perché il tuo programma utilizzi una memoria eccessiva, ma potresti voler controllare quanto sta usando. Pubblicare il codice può essere utile per noi cercando di risolvere i problemi qui. – hBrent

+0

Ok sicuro di non avere problemi. Ma quale parte del codice vorresti che aggiungessi esattamente? –

+0

Chiama a 'bluetoothServerSocket.close();' genera un'eccezione quando non è stata stabilita alcuna connessione? – Houf

risposta

0

Penso di aver trovato una soluzione per questo problema. Il "Credo" è perché questo non è stato ancora testato su molti dispositivi.Codice

sotto è Scala

Per la soluzione Approfitto del metodo di overload accettare (int) che ha un timeout

quindi abbiamo una variabile per lo stato del ciclo infinito si sta vedendo sotto

private var toContinue = true; 

Abbiamo appena ripetiamo accettare in un ciclo while

0.123.
while (toContinue) { 
    try { 
    //this is a blocking call and will only return on a successful connection or an exception, or on timeout 
    val socket = bluetoothServerSocket.accept(10000); //msec 

    connectionAccepted(socket); 
    } catch { 
    case e: IOException => { 
     Logger("accepting timed out"); 
    } 
    } 
} 

Così ora invece di chiamare il bluetoothServerSocket.close() stiamo solo impostando la variabile su false

def cancel() { 
    toContinue = false; 
} 

codice attuale è un po 'più complessa in quanto è necessario una funzione di callback per fare qualcosa su l'uscita del ciclo while ma il problema principale è risolto come mostrato sopra

2

I La chiusura del socket causa così tanto danno, quindi perché non creare un flag booleano impostato su true quando l'utente è connesso e impostato su false quando l'utente si disconnette; quindi chiama solo chiudi quando l'utente era precedentemente connesso.

+0

La tua soluzione è ok ma l'hai provata e hai riscontrato lo stesso problema di me? –

+0

No Non ho visto lo stesso problema che stai descrivendo e non l'ho ancora testato ma ha senso solo chiudere il socket se era stato aperto in precedenza. Essere d'accordo? – Jeremy

+0

Il socket è effettivamente aperto ma non è collegato (non ancora accettato) .. E se ricordo correttamente da altre letture in Internet se si lascia aperta una presa del server bluetooth in ascolto, si spende molta batteria. Un motivo in più è che le prese di ascolto non sono infinite. Quindi aprire un nuovo socket ~ 20 volte è sufficiente per ottenere un'eccezione –

6

Ho riscontrato un problema simile e la causa principale del problema era la chiamata su un socket più di una volta. Per correggere questo problema, ho avvolto i miei socket bluetooth in una classe speciale per impedire che il metodo close venisse chiamato più di una volta.

Tenere presente che la chiusura dei flussi creati da una presa bluetooth è in grado di chiamare da vicino sul socket. Il seguente risolve il problema.

public class CloseOnceBluetoothSocket 
{ 
private final BluetoothSocket mSocket; 
private boolean mIsClosed; 

public CloseOnceBluetoothSocket(BluetoothSocket socket) 
{ 
    this.mSocket = socket; 
} 

public void connect() throws IOException 
{ 
    mSocket.connect(); 
} 

public InputStream getInputStream() throws IOException 
{ 
    return new FilterInputStream(mSocket.getInputStream()) { 
     @Override 
     public void close() throws IOException 
     { 
      CloseOnceBluetoothSocket.this.close(); 
     } 
    }; 
} 

public OutputStream getOutputStream() throws IOException 
{ 
    return new FilterOutputStream(mSocket.getOutputStream()) { 
     @Override 
     public void close() throws IOException 
     { 
      CloseOnceBluetoothSocket.this.close(); 
     } 
    }; 
} 

public void close() throws IOException 
{ 
    synchronized (mSocket) { 
     if (!mIsClosed) { 
      mSocket.close(); 
      mIsClosed = true; 
     } 
    } 
} 
} 
+0

Grazie Justin. Terrò la tua classe perché potrebbe essere utile in altre situazioni. Ho sostituito tutti i pezzi del mio codice con CloseOnceBluetoothSocket ma sfortunatamente questo non ha fatto la differenza. Non ho un problema con la chiusura di una presa bluetooth il problema è la chiusura di un socket ** bluetooth ** server. Sto ancora ricevendo questo: 'Processo 9414 terminato dal segnale (11) .' Ma suppongo che devo trovare una soluzione alternativa alla tua o decidere che API 10 è troppo bacato per la mia situazione e forse una nuova API avrebbe risolto questo problema. Grazie comunque! –

+0

Avete implementato una soluzione simile per il socket del vostro server? –

+0

Sì!L'ho già fatto usando solo e se la dichiarazione. Ma non c'è alcun problema di eseguire l'arresto due volte. L'intera faccenda si blocca alla prima chiamata .. !! –

Problemi correlati