Android BluetoothSocket write falla en 4.2.2
Estoy probando tanto en un ASUS MemoPad HD (4.2.2) como en un LG P769 (4.1.2). Escribí un programa sencillo para ilustrar mi problema:
package wat.bluetoothtester; import java.util.*; import java.io.*; import android.app.Activity; import android.os.Bundle; import android.bluetooth.*; import android.view.*; import android.util.*; public class BluetoothTester extends Activity { private final String ADDR = "00:02:72:C6:C2:3C"; private final UUID _UUID = UUID.fromString("ca444490-3569-4c82-b505-defbc71e9868"); private BluetoothSocket _socket; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void send(View v){ try { this._socket.getOutputStream().write('x'); } catch (IOException e){ Log.e("", e.toString()); } } public void connect(View v){ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device = adapter.getRemoteDevice(ADDR); try { this._socket = device.createInsecureRfcommSocketToServiceRecord(_UUID); this._socket.connect(); } catch (IOException e){ Log.e("", e.toString()); } } public void disconnect(View v){ try { this._socket.close(); } catch (IOException e){ Log.e("", e.toString()); } } }
Bloquea, lo sé, pero ese no es el problema. Tiene un diseño simple con 3 botones, como usted puede ser capaz de adivinar el código. Voy a publicar si es necesario. También tengo un servidor Python simple que se ejecuta en mi computadora, que simplemente escupe los datos que recibe, y nunca envía ningún dato.
- Cambiar el color de línea inferior de EditText con appcompat v7
- Verificar la firma SHA1withRSA generada en Java (Android) con phpseclib
- ¿Cómo comparar dos arraylist?
- Cifrado utilizando AES-128 en Android e IPhone (Resultado diferente)
- Android WebView personalizado no logra encontrar funciones de javascript definidas en HTML cargado
De todos modos, la primera vez que ejecutar esto en mi dispositivo 4.2.2, funciona muy bien. Puedo conectar y desconectar a voluntad, enviar datos, no hay problema. Ahora, ya que estoy desarrollando una aplicación, tengo que empujar con frecuencia un nuevo APK al dispositivo. Tan pronto como hago esto, o no me desconecto, las escrituras comienzan a fallar. La parte más extraña es que el servidor realmente recibe los datos y lo imprime, pero las llamadas write () siguen bloqueando:
11-19 12:34:30.127: E/(3484): java.io.IOException: [JSR82] write: write() failed. 11-19 12:34:30.127: E/(3484): at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:702) 11-19 12:34:30.127: E/(3484): at android.bluetooth.BluetoothOutputStream.write(BluetoothOutputStream.java:56) 11-19 12:34:30.127: E/(3484): at wat.bluetoothtester.BluetoothTester.send(BluetoothTester.java:29) 11-19 12:34:30.127: E/(3484): at java.lang.reflect.Method.invokeNative(Native Method) 11-19 12:34:30.127: E/(3484): at java.lang.reflect.Method.invoke(Method.java:511) 11-19 12:34:30.127: E/(3484): at android.view.View$1.onClick(View.java:3633) 11-19 12:34:30.127: E/(3484): at android.view.View.performClick(View.java:4243) 11-19 12:34:30.127: E/(3484): at android.view.View$PerformClick.run(View.java:17520) 11-19 12:34:30.127: E/(3484): at android.os.Handler.handleCallback(Handler.java:725) 11-19 12:34:30.127: E/(3484): at android.os.Handler.dispatchMessage(Handler.java:92) 11-19 12:34:30.127: E/(3484): at android.os.Looper.loop(Looper.java:153) 11-19 12:34:30.127: E/(3484): at android.app.ActivityThread.main(ActivityThread.java:5299) 11-19 12:34:30.127: E/(3484): at java.lang.reflect.Method.invokeNative(Native Method) 11-19 12:34:30.127: E/(3484): at java.lang.reflect.Method.invoke(Method.java:511) 11-19 12:34:30.127: E/(3484): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) 11-19 12:34:30.127: E/(3484): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 11-19 12:34:30.127: E/(3484): at dalvik.system.NativeStart.main(Native Method)
Tan claramente esto lanza una IOException, aunque los datos se han enviado con éxito. Esto significa que el programa funciona técnicamente, pero write () bloquea la interfaz de usuario durante unos 10-15 segundos hasta que se genera la excepción. He intentado poner el write () en su propio hilo, a continuación, sólo la creación de un buffer TX que se vacía a voluntad. Esto, por supuesto, no causa que la interfaz de usuario bloquee, pero necesito esperar el tiempo de espera write (), por lo que tampoco me ayuda realmente. Este es el caso hasta que reinicie el dispositivo. Conectar / desconectar ambos siguen funcionando bien.
Esto no sucede en mi dispositivo 4.1.2, no importa cuántas veces subo un nuevo APK o mato el proceso.
También he confirmado el mismo problema cuando se utiliza BlueTerm, una aplicación de tipo terminal para las conexiones serie RFCOMM (en realidad es bastante bueno, además de la fuente está disponible).
Tengo los dos dispositivos enraizados, y realmente no quiero ir por este camino, pero hay una manera de reiniciar el servicio Bluetooth o purgar manualmente el grupo de conexiones, o algo así?
- AndEngine - eliminar un Sprite particular y su cuerpo
- Android lanzar SMS intención sin ningún destinatario
- ¿Dónde escribir @Override?
- JNI Android - Convertir char * en matriz de bytes y devolverlo a java
- Altura de la vista de notificación de estado personalizado de Android
- ¿Cómo obtengo una variable de un bloque try / catch?
- ActivityCompat.requestPermissions no muestra el mensaje
- Android - Apache Mime y httpClient
La implementación de MediaTek JNI de la JSR82 para Android no funciona muy bien
- Android_server_BluetoothSocketService.cpp (writeNative (): Mucho tiempo sin ver un goto)
- BluetoothSocketService.java
- BluetoothSocket.java
Crea una matriz para almacenar el contexto de las conexiones:
btmtk_jsr82_mmi_context_struct g_jsr82MMIContext[JSR82_PORT_NUM];
Cuando se crea un nuevo socket, utiliza la primera posición de contexto no inUse y, a menos que cierre el socket correctamente (tenga en cuenta que se trata de un servicio compartido), el indicador inUse no se borra.
El problema es que sólo g_jsr82MMIContext [0] parece recibir los eventos EVENT_JSR82_MMI_TX_READY_IND correctamente al final de un write ()
Los descriptores de los ficheros sockets parecen ser codificados y para el socket en g_jsr82MMICicon [0] es 0x8000, por lo que con la reflexión se puede "falsificar" ese socket y cerrarlo para limpiar el indicador g_jsr82MMIContext [0] .inUse, de modo que la próxima vez será Disponible
public void connect(View v){ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device = adapter.getRemoteDevice(ADDR); try { BluetoothSocket bs = device.createRfcommSocketToServiceRecord(_UUID); Field f = bs.getClass().getDeclaredField("mFdHandle"); f.setAccessible(true); f.set(bs, 0x8000); bs.close(); Thread.sleep(2000); // Just in case the socket was really connected } catch (Exception e) { Log.e(TAG, "Reset Failed", e); } try { this._socket = device.createRfcommSocketToServiceRecord(_UUID); this._socket.connect(); } catch (IOException e) { Log.e(TAG, "create() failed", e); } }
Jla funciona bien para una sola conexión Bluetooth. Si hay más de una conexión Bluetooth, digamos dos conexiones, el método desconecta ambas conexiones en lugar de una conexión determinada.
Alguien tiene idea para resolver más de un caso de conexión?
- Cómo deshabilitar el botón mientras AsyncTask se está ejecutando? (Androide)
- Quiero almacenar la imagen en la base de datos sqlite que se toma de galería y cámara Android