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.

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í?

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?

  • Lista de la documentación de Android Ver ejemplo Código fuente en XML
  • Respuesta de JSON de Django en Android
  • Deshabilitar la comprobación de certificados SSL en la biblioteca de actualización
  • Android.view.InflateException: Línea de archivo XML binario # 9: Error al inflar la clase <unknown>
  • ¿Cómo se simula la memoria baja en el emulador de Android?
  • Cómo utilizar un carácter como un separador en una cadena
  • Mantener el vibrador funcionando en modo de reposo
  • Requiere el proyecto Gradle desde otro directorio
  • Convertir cadena en formato de fecha
  • No se pudo encontrar el método en el contexto padre o antepasado
  • Java Dates - ¿Cuál es la clase correcta para usar?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.