studio scanner libreria ejemplo detectar conexion android bluetooth motorola rfcomm

scanner - modulo bluetooth en android studio



Cómo evitar que la conexión RFCOMM Bluetooth de Android muera inmediatamente después de.connect()? (5)

¡Este problema ha sido resuelto! ¡Muchas gracias a Brad, Denis y yonqui! ¡Ustedes son los héroes! :)

Este es el código de trabajo. Se conecta a Zeemote y lee datos de él.

===== Código =====

public class ZeeTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { for (int i = 0; i < 3; i++) { test(); } } catch (Exception e) { e.printStackTrace(); } } private boolean connected = false; private BluetoothSocket sock; private InputStream in; public void test() throws Exception { if (connected) { return; } BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter(). getRemoteDevice("00:1C:4D:02:A6:55"); Method m = zee.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); sock = (BluetoothSocket)m.invoke(zee, Integer.valueOf(1)); Log.d("ZeeTest", "++++ Connecting"); sock.connect(); Log.d("ZeeTest", "++++ Connected"); in = sock.getInputStream(); byte[] buffer = new byte[50]; int read = 0; Log.d("ZeeTest", "++++ Listening..."); try { while (true) { read = in.read(buffer); connected = true; StringBuilder buf = new StringBuilder(); for (int i = 0; i < read; i++) { int b = buffer[i] & 0xff; if (b < 0x10) { buf.append("0"); } buf.append(Integer.toHexString(b)).append(" "); } Log.d("ZeeTest", "++++ Read "+ read +" bytes: "+ buf.toString()); } } catch (IOException e) {} Log.d("ZeeTest", "++++ Done: test()"); } @Override public void onDestroy() { try { if (in != null) { in.close(); } if (sock != null) { sock.close(); } } catch (IOException e) { e.printStackTrace(); } super.onDestroy(); } }

===== Pregunta original =====

Intento conectarme con un Zeemote ( http://zeemote.com/ ) controlador de juego de Moto Droid ejecutando el firmware 2.0.1. La aplicación de prueba a continuación se conecta al dispositivo (el LED parpadea) pero la conexión se corta inmediatamente después de eso.

Estoy pegando dos aplicaciones de prueba a continuación: una que realmente intenta leer desde el flujo de entrada y la segunda que se queda allí, esperando a que el dispositivo se desconecte después de 5 segundos. Y sí, tengo una tercera versión :) que primero espera ACL_CONNECTED y luego abre socket pero no hay nada nuevo en su comportamiento.

Información de fondo: puedo conectarme al Zeemote desde mi computadora portátil perfectamente bien usando las herramientas bluez (también se adjunta el registro). Sé con certeza que Droid también puede hablar con Zeemote porque ''Game Pro'' de Market funciona bien con él (pero entonces es un controlador / servicio, ¿entonces quizás usa un API de nivel inferior?).

Noté que ''adb bugreport'' no informa el UUID ni el canal RFCOMM para Zeemote mientras que lo hace para todos los demás dispositivos (incluido el auricular Moto HS815, otro dispositivo tonto para el cual ''sdp browse'' no informa nada). Además, cuando se inicia el dispositivo, la prioridad de Zeemote es 0 (otros tienen prioridad de más de 100).

Estoy bastante perdido aquí, trabajé tanto tiempo que me quedé sin ideas por lo que cualquier ayuda sería muy apreciada (incluso si no sabes la respuesta :))

Gracias, Max

Aplicación de prueba n. ° 1

Esta aplicación intenta leer realmente desde el dispositivo.

===== Código =====

public class ZeeTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { test(); } catch (IOException e) { e.printStackTrace(); } } private BluetoothSocket sock; private InputStream in; public void test() throws IOException { BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter(). getRemoteDevice("00:1C:4D:02:A6:55"); sock = zee.createRfcommSocketToServiceRecord( UUID.fromString("8e1f0cf7-508f-4875-b62c-fbb67fd34812")); Log.d("ZeeTest", "++++ Connecting"); sock.connect(); Log.d("ZeeTest", "++++ Connected"); in = sock.getInputStream(); byte[] buffer = new byte[1]; int bytes = 0; int x = 0; Log.d("ZeeTest", "++++ Listening..."); while (x < 2) { x++; try { bytes = in.read(buffer); Log.d("ZeeTest", "++++ Read "+ bytes +" bytes"); } catch (IOException e) { e.printStackTrace(); try { Thread.sleep(100); } catch (InterruptedException ie) {} } } Log.d("ZeeTest", "++++ Done: test()"); } @Override public void onDestroy() { try { if (in != null) { in.close(); } if (sock != null) { sock.close(); } } catch (IOException e) { e.printStackTrace(); } super.onDestroy(); } }

===== Log =====

04-19 22:27:01.147: DEBUG/ZeeTest(8619): ++++ Connecting 04-19 22:27:04.085: INFO/usbd(1062): process_usb_uevent_message(): buffer = add@/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:27:04.085: INFO/usbd(1062): main(): call select(...) 04-19 22:27:04.327: ERROR/BluetoothEventLoop.cpp(4029): event_filter: Received signal org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04-19 22:27:04.491: VERBOSE/BluetoothEventRedirector(7499): Received android.bleutooth.device.action.UUID 04-19 22:27:04.905: DEBUG/ZeeTest(8619): ++++ Connected 04-19 22:27:04.905: DEBUG/ZeeTest(8619): ++++ Listening... 04-19 22:27:05.538: WARN/System.err(8619): java.io.IOException: Software caused connection abort 04-19 22:27:05.600: WARN/System.err(8619): at android.bluetooth.BluetoothSocket.readNative(Native Method) ... 04-19 22:27:05.717: WARN/System.err(8619): java.io.IOException: Software caused connection abort 04-19 22:27:05.717: WARN/System.err(8619): at android.bluetooth.BluetoothSocket.readNative(Native Method) ... 04-19 22:27:05.819: DEBUG/ZeeTest(8619): ++++ Done: test() 04-19 22:27:07.155: VERBOSE/BluetoothEventRedirector(7499): Received android.bleutooth.device.action.UUID 04-19 22:27:09.077: INFO/usbd(1062): process_usb_uevent_message(): buffer = remove@/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:27:09.085: INFO/usbd(1062): main(): call select(...) 04-19 22:27:09.139: ERROR/BluetoothEventLoop.cpp(4029): event_filter: Received signal org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55

Solicitud de prueba n. ° 2

Esta prueba se conecta y espera, útil para mostrar el problema de autodesconexión.

===== Código =====

public class ZeeTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)); getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); try { BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter(). getRemoteDevice("00:1C:4D:02:A6:55"); sock = zee.createRfcommSocketToServiceRecord( UUID.fromString("8e1f0cf7-508f-4875-b62c-fbb67fd34812")); Log.d("ZeeTest", "++++ Connecting"); sock.connect(); Log.d("ZeeTest", "++++ Connected"); } catch (IOException e) { e.printStackTrace(); } } private static final LogBroadcastReceiver receiver = new LogBroadcastReceiver(); public static class LogBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("ZeeReceiver", intent.toString()); Bundle extras = intent.getExtras(); for (String k : extras.keySet()) { Log.d("ZeeReceiver", " Extra: "+ extras.get(k).toString()); } } } private BluetoothSocket sock; @Override public void onDestroy() { getApplicationContext().unregisterReceiver(receiver); if (sock != null) { try { sock.close(); } catch (IOException e) { e.printStackTrace(); } } super.onDestroy(); } }

===== Log =====

04-19 22:06:34.944: DEBUG/ZeeTest(7986): ++++ Connecting 04-19 22:06:38.202: INFO/usbd(1062): process_usb_uevent_message(): buffer = add@/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:06:38.202: INFO/usbd(1062): main(): call select(...) 04-19 22:06:38.217: ERROR/BluetoothEventLoop.cpp(4029): event_filter: Received signal org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04-19 22:06:38.428: VERBOSE/BluetoothEventRedirector(7499): Received android.bleutooth.device.action.UUID 04-19 22:06:38.968: DEBUG/ZeeTest(7986): ++++ Connected 04-19 22:06:39.061: DEBUG/ZeeReceiver(7986): Intent { act=android.bluetooth.device.action.ACL_CONNECTED (has extras) } 04-19 22:06:39.108: DEBUG/ZeeReceiver(7986): Extra: 00:1C:4D:02:A6:55 04-19 22:06:39.538: INFO/ActivityManager(4029): Displayed activity zee.test/.ZeeTest: 5178 ms (total 5178 ms) 04-19 22:06:41.014: VERBOSE/BluetoothEventRedirector(7499): Received android.bleutooth.device.action.UUID 04-19 22:06:43.038: INFO/usbd(1062): process_usb_uevent_message(): buffer = remove@/devices/virtual/bluetooth/hci0/hci0:1 04-19 22:06:43.038: INFO/usbd(1062): main(): call select(...) 04-19 22:06:43.069: ERROR/BluetoothEventLoop.cpp(4029): event_filter: Received signal org.bluez.Device:PropertyChanged from /org/bluez/4121/hci0/dev_00_1C_4D_02_A6_55 04-19 22:06:43.124: DEBUG/ZeeReceiver(7986): Intent { act=android.bluetooth.device.action.ACL_DISCONNECTED (has extras) } 04-19 22:06:43.124: DEBUG/ZeeReceiver(7986): Extra: 00:1C:4D:02:A6:55

Registros del sistema

===== Registro de terminal =====

$ sdptool browse Inquiring ... Browsing 00:1C:4D:02:A6:55 ... $ sdptool records 00:1C:4D:02:A6:55 Service Name: Zeemote Service RecHandle: 0x10015 Service Class ID List: UUID 128: 8e1f0cf7-508f-4875-b62c-fbb67fd34812 Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 1 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 $ rfcomm connect /dev/tty10 00:1C:4D:02:A6:55 Connected /dev/rfcomm0 to 00:1C:4D:02:A6:55 on channel 1 Press CTRL-C for hangup # rfcomm show /dev/tty10 rfcomm0: 00:1F:3A:E4:C8:40 -> 00:1C:4D:02:A6:55 channel 1 connected [reuse-dlc release-on-hup tty-attached] # cat /dev/tty10 (nothing here) # hcidump HCI sniffer - Bluetooth packet analyzer ver 1.42 device: hci0 snap_len: 1028 filter: 0xffffffff < HCI Command: Create Connection (0x01|0x0005) plen 13 > HCI Event: Command Status (0x0f) plen 4 > HCI Event: Connect Complete (0x03) plen 11 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 > HCI Event: Read Remote Supported Features (0x0b) plen 11 < ACL data: handle 11 flags 0x02 dlen 10 L2CAP(s): Info req: type 2 > HCI Event: Command Status (0x0f) plen 4 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 > HCI Event: Max Slots Change (0x1b) plen 3 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 > HCI Event: Command Status (0x0f) plen 4 > ACL data: handle 11 flags 0x02 dlen 16 L2CAP(s): Info rsp: type 2 result 0 Extended feature mask 0x0000 < ACL data: handle 11 flags 0x02 dlen 12 L2CAP(s): Connect req: psm 3 scid 0x0040 > HCI Event: Number of Completed Packets (0x13) plen 5 > ACL data: handle 11 flags 0x02 dlen 16 L2CAP(s): Connect rsp: dcid 0x04fb scid 0x0040 result 1 status 2 Connection pending - Authorization pending > HCI Event: Remote Name Req Complete (0x07) plen 255 > ACL data: handle 11 flags 0x02 dlen 16 L2CAP(s): Connect rsp: dcid 0x04fb scid 0x0040 result 0 status 0 Connection successful < ACL data: handle 11 flags 0x02 dlen 16 L2CAP(s): Config req: dcid 0x04fb flags 0x00 clen 4 MTU 1013 (events are properly received using bluez)

===== Parte de adb bugreport =====

--Known devices-- 00:19:A1:2D:16:EA bonded (0) LG U830 00001105-0000-1000-8000-00805f9b34fb RFCOMM channel = 17 00:1C:4D:02:A6:55 bonded (0) Zeemote JS1 00:0B:2E:6E:6F:00 bonded (0) Motorola HS815 00001108-0000-1000-8000-00805f9b34fb RFCOMM channel = 1 0000111e-0000-1000-8000-00805f9b34fb RFCOMM channel = 2 00:1F:3A:E4:C8:40 bonded (0) BRCM BT4X 00001105-0000-1000-8000-00805f9b34fb RFCOMM channel = 9 00:18:42:EC:E2:99 bonded (0) N95 00001105-0000-1000-8000-00805f9b34fb RFCOMM channel = 9

===== Extracto del registro de inicio de sesión =====

04-18 21:55:10.382: VERBOSE/BluetoothEventRedirector(1985): Received android.bluetooth.adapter.action.STATE_CHANGED 04-18 21:55:10.421: DEBUG/BT HSHFP(1237): Loaded priority 00:19:A1:2D:16:EA = 100 04-18 21:55:10.428: DEBUG/BT HSHFP(1237): Loaded priority 00:1C:4D:02:A6:55 = 0 04-18 21:55:10.444: DEBUG/BT HSHFP(1237): Loaded priority 00:0B:2E:6E:6F:00 = 101 04-18 21:55:10.749: DEBUG/BT HSHFP(1237): Loaded priority 00:1F:3A:E4:C8:40 = 100 04-18 21:55:10.780: DEBUG/BT HSHFP(1237): Loaded priority 00:18:42:EC:E2:99 = 100


El código anterior no funcionó en la pestaña 2 de Samsung Galaxy con 4.0.4. BTSocket.connect siempre activó el diálogo de emparejamiento con bluetooth y luego falló, incluso si se escribió el pin correcto. Cambiar de "createRfcommSocket" a "createInsecureRfcommSocket" resolvió el problema. Espero que esto ayude, luché con este problema por más de 3 horas.


Fusioné el código que había escrito y el código de [android-beginners] Re: Serial over Bluetooth by XCaffeinated] 1 y la publicación anterior.

Para crear el programa bluetooth más simple posible.

La principal adición para este código es agregar un mejor manejo en las excepciones lanzadas por connect() .

Busque ''@todo'' para personalizarlo según sus necesidades.

¡Espero que esto te ahorre algo de tiempo!

package com.xxx; // @todo Change to your package. import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.os.Bundle; import android.util.Log; /** * This is the simplest bluetooth program. It sends one message to one bluetooth * device. The message and the bluetooth hardware id for the device are hard * coded. <br> * <br> * It does <b>not</b> receive any data. It does not do any thread processing. <br> * <br> * * This application will be useful to communicate with a bluetooth hardware * device such as a bar code reader, Lego Mindstorm, a PC with a com port * application, a PC with a terminal program with ''listening'' to a com port, a * second android device with a terminal program such as <a href= * "http://www.tec-it.com/en/software/data-acquisition/getblue/android-smartphone/Default.aspx" * >GetBlue</a>. It is not a full android bluetooth application but more a proof * of concept that the bluetooth works. * * <br> * <br> * * This code should cut and paste into the <a * href="http://developer.android.com/resources/tutorials/hello-world.html> * ''HelloAndroid'' example</a>. It does not use any screen io. * * Add to your Android Manifest.xml file: <uses-permission * android:name="android.permission.BLUETOOTH" /> <uses-permission * android:name="android.permission.BLUETOOTH_ADMIN" /> * * For a proper bluetooth example with threading and receiving data see: <a * href= * "http://developer.android.com/resources/samples/BluetoothChat/index.html" * >http://developer.android.com/resources/samples/BluetoothChat/index.html</a> * * @see <a * href="http://developer.android.com/guide/topics/wireless/bluetooth.html"> * http://developer.android.com/guide/topics/wireless/bluetooth.html</a> * */ public class BlueToothTesterActivity extends Activity { /** The BluetoothAdapter is the gateway to all bluetooth functions **/ protected BluetoothAdapter bluetoothAdapter = null; /** We will write our message to the socket **/ protected BluetoothSocket socket = null; /** The Bluetooth is an external device, which will receive our message **/ BluetoothDevice blueToothDevice = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Grab the BlueToothAdapter. The first line of most bluetooth programs. bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // if the BluetoothAdapter.getDefaultAdapter(); returns null then the // device does not have bluetooth hardware. Currently the emulator // does not support bluetooth so this will this condition will be true. // i.e. This code only runs on a hardware device an not on the emulator. if (bluetoothAdapter == null) { Log.e(this.toString(), "Bluetooth Not Available."); return; } // This will find the remote device given the bluetooth hardware // address. // @todo: Change the address to the your device address blueToothDevice = bluetoothAdapter.getRemoteDevice("00:00:00:00:00:00"); for (Integer port = 1; port <= 3; port++) { simpleComm(Integer.valueOf(port)); } } protected void simpleComm(Integer port) { // byte [] inputBytes = null; // The documents tell us to cancel the discovery process. bluetoothAdapter.cancelDiscovery(); Log.d(this.toString(), "Port = " + port); try { // This is a hack to access "createRfcommSocket which is does not // have public access in the current api. // Note: BlueToothDevice.createRfcommSocketToServiceRecord (UUID // uuid) does not work in this type of application. . Method m = blueToothDevice.getClass().getMethod( "createRfcommSocket", new Class[] { int.class }); socket = (BluetoothSocket) m.invoke(blueToothDevice, port); // debug check to ensure socket was set. assert (socket != null) : "Socket is Null"; // attempt to connect to device socket.connect(); try { Log.d(this.toString(), "************ CONNECTION SUCCEES! *************"); // Grab the outputStream. This stream will send bytes to the // external/second device. i.e it will sent it out. // Note: this is a Java.io.OutputStream which is used in several // types of Java programs such as file io, so you may be // familiar with it. OutputStream outputStream = socket.getOutputStream(); // Create the String to send to the second device. // Most devices require a ''/r'' or ''/n'' or both at the end of the // string. // @todo set your message String message = "Data from Android and tester program!/r"; // Convert the message to bytes and blast it through the // bluetooth // to the second device. You may want to use: // public byte[] getBytes (Charset charset) for proper String to // byte conversion. outputStream.write(message.getBytes()); } finally { // close the socket and we are done. socket.close(); } // IOExcecption is thrown if connect fails. } catch (IOException ex) { Log.e(this.toString(), "IOException " + ex.getMessage()); // NoSuchMethodException IllegalAccessException // InvocationTargetException // are reflection exceptions. } catch (NoSuchMethodException ex) { Log.e(this.toString(), "NoSuchMethodException " + ex.getMessage()); } catch (IllegalAccessException ex) { Log.e(this.toString(), "IllegalAccessException " + ex.getMessage()); } catch (InvocationTargetException ex) { Log.e(this.toString(), "InvocationTargetException " + ex.getMessage()); } } }


Intenta cambiar tu código para crear RfcommSocket:

sock = zee.createRfcommSocketToServiceRecord( UUID.fromString("8e1f0cf7-508f-4875-b62c-fbb67fd34812"));

para este código:

Method m = zee.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); sock = (BluetoothSocket) m.invoke(device, 1);

Intente también cambiar el valor del argumento en el rango 1-3 en este m.invoke (dispositivo, 1); Cuando la conexión se conecte, pero se interrumpa cuando intente leer, llame de nuevo a su prueba de método (). Tan simple:

for(int i=0;i<3;i++){ if(!testDone) test(); }


Pruebe el conocido UUID: 00001101-0000-1000-8000-00805F9B34FB


Si entiendo correctamente, su aplicación no puede ver ningún dato del dispositivo en absoluto.

Una pequeña cosa: prueba tu UUID sin hiphens. En mis aplicaciones RFCOMM realmente defino el UUID como una constante entera larga.

Además, la forma en que se escribe su método de prueba () me lleva a creer que la prueba () está haciendo la conexión, definiendo un hilo, diciéndole que comience y que vuelva de inmediato. En otras palabras, su hilo está haciendo referencia a una variable desde fuera del hilo que forma parte del método de prueba () pero cuando test () muere, también lo hacen sus variables.

En resumen, pruebe sus pruebas fuera de un hilo y haga que funcione allí primero. Una manera fácil de hacerlo sería usar Thread.run () en lugar de thread.start (). .run () lo ejecuta en primer plano (y por lo tanto bloquea la prueba () para que no vuelva antes de que termine el hilo).

Para una solución a más largo plazo, quizás desee definir sus variables Bluetooth como variables global / member para que no salgan del alcance y estén siempre disponibles para su hilo.