studio activar android bluetooth serversocket

android - activar - Al cancelar el socket del servidor bluetooth antes de aceptar, todo el proceso muere. ¿Por qué?



bluetooth android studio (3)

Estoy compilando para SDK 10 (2.3.3):

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

Estoy probando en dos teléfonos inteligentes Sony Ericsson. Uno tiene Android 2.3.7 y el otro 4.0.1.

Estoy usando listenUsingInsecureRfcommWithServiceRecord para abrir un nuevo socket de servidor en bluetooth y escuchar las conexiones.

Si la conexión se acepta con éxito, todo funciona bien. Incluso puedo intentar cancelar el socket del servidor, pero eso no parece molestar al socket de conexión que acaba de crear.

PERO cuando quiero cancelar el socket del servidor antes de haber aceptado cualquier conexión tan pronto como la línea bluetoothServerSocket.close(); se ejecuta toda la actividad se cierra y el proceso muere. Y, además, esta no es una excepción regular que podría manejar.

En realidad, ¡incluso Logcat se cierra! y tengo que ejecutarlo de nuevo rápidamente para captar los errores que puedes ver a continuación:

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 android.os.BinderProxy@2bf3e798 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: El proceso terminado por la señal (11) significa falla de segmentación ( http://en.wikipedia.org/wiki/SIGSEGV ).

EDITAR

Creo el socket del servidor Bluetooth usando el siguiente código ( Scala ):

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

Utilizo este código para cerrar el socket Bluetooth :

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


Si cerrar el socket causa tanto daño, ¿por qué no simplemente crear un indicador booleano que se establece en verdadero cuando el usuario está conectado y configurado en falso cuando el usuario se desconecta? luego solo se llama cuando el usuario estuvo conectado anteriormente.


He experimentado un problema similar y la causa raíz del problema fue llamar cerca de un socket más de una vez. Para corregir este problema, envolví mis conectores bluetooth en una clase especial para evitar que se llamara al método de cierre más de una vez.

Tenga en cuenta que el cierre de las transmisiones creadas por un socket bluetooth es capaz de llamar cerca del socket. Lo siguiente resuelve el 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; } } } }


Creo que he encontrado una solución para este problema. El "Creo" es porque esto aún no se ha probado en muchos dispositivos.

el siguiente código es Scala

Para la solución, aprovecho el método sobrecargado accept (int) que tiene un tiempo de espera excedido

Entonces, tenemos una variable para el estado del ciclo infinito que está viendo debajo

private var toContinue = true;

Simplemente repetimos aceptando en un ciclo while

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"); } } }

Así que ahora, en lugar de llamar a bluetoothServerSocket.close() , solo estamos configurando variables como falsas

def cancel() { toContinue = false; }

El código real es un poco más complejo ya que necesita una función de devolución de llamada para hacer algo a la salida del ciclo while, pero el problema principal se resuelve como se muestra arriba.