2010-08-03 10 views
47

Actualmente estoy trabajando en una aplicación de Android que se conecta a un instrumento a través de Bluetooth y necesita escribir comandos de cadena y recibir respuestas de cadena. Actualmente tengo el trabajo de conexión/lectura/escritura para TCP/IP a través de Wi-Fi y ahora intento implementar Bluetooth. Pero estoy tropezando con algunos obstáculos. He estado buscando en la web tratando de encontrar ejemplos de algo similar y no he tenido suerte. He estado usando el ejemplo de recursos de desarrollador de Android: Bluetooth Chat como mi principal punto de referencia.Error de descubrimiento de servicio excepción usando Bluetooth en Android

Parece que mi código actual funciona. A continuación, arroja una excepción de detección de servicio fallido en el punto de la conexión. Estoy usando la clase DeviceListActivity para hacer el descubrimiento y seleccionar el dispositivo al que deseo conectarme. Devuelve anActivityResult y luego mi clase Bluetooth espera que lo maneje y luego se conecta. El código debajo es casi idéntico a la aplicación Bluetooth Chat.

public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if(!m_BluetoothAdapter.isEnabled()) 
    { 
     m_BluetoothAdapter.enable(); 
    } 
    switch (requestCode) { 
     case REQUEST_CONNECT_DEVICE: 
      // When DeviceListActivity returns with a device to connect 
      if (resultCode == Activity.RESULT_OK) { 
       // Get the device MAC address 
       String address = data.getExtras() 
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); 
       // Get the BLuetoothDevice object 
       BluetoothDevice device = m_BluetoothAdapter.getRemoteDevice(address); 
       // Attempt to connect to the device 
       connect(device); 
      } 
      break; 

     case REQUEST_ENABLE_BT: 
      // When the request to enable Bluetooth returns 
      if (resultCode == Activity.RESULT_OK) { 
       // Bluetooth is now enabled, so set up a chat session 
      } 
      else { 
       // User did not enable Bluetooth or an error occured 

       Toast.makeText(this, "Bluetooth not enabled", Toast.LENGTH_SHORT).show(); 
       finish(); 
      } 
    } 
} 

Ésta es mi función de conexión:

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 

private void connect(BluetoothDevice device) { 
    m_Device = device; 
    BluetoothSocket tmp = null; 

    // Get a BluetoothSocket for a connection with the 
    // given BluetoothDevice 
    try { 
     tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 
    } 
    catch (IOException e) { 

    } 
    m_Socket = tmp; 

    m_BluetoothAdapter.cancelDiscovery(); 

    try { 
     // This is a blocking call and will only return on a 
     // successful connection or an exception 
     m_Socket.connect(); 
    } 
    catch (IOException e) { 
     try { 
      m_Socket.close(); 
     } 
     catch (IOException e2) { 
     } 
     return; 
    } 
} 

Con suerte, lo que estoy haciendo mal es simple, pero me temo que no es tan fácil. Esta es la primera vez que hago un desarrollo de Bluetooth, y tal vez estoy haciendo algo descaradamente mal ... Pero no estoy seguro de por qué recibo la excepción de descubrimiento de servicio fallido.

Puede emparejar/buscar el dispositivo en todo momento manualmente en el teléfono ... Requiere un código de acceso, pero no creo que ese sea el problema que estoy teniendo.

Respuesta

92

Después de tres días lo entendí gracias a algunas publicaciones muy útiles.

que tuvieron que reemplazar:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

con:

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

y listo funciona!

+1

Espera, tengo un par de aplicaciones Bluetooth y yo no he encontrado una situación donde el uso de la reflexión (getclass.getmethod) sea necesario. ¿Puedes decirme un poco más sobre qué hardware probaste? Estoy muy interesado en saber si la reflexión es realmente necesaria en ciertas situaciones. –

+0

Después de algunas pruebas. Descubrí que en realidad era el teléfono el que tenía problemas con él. El HTC Incredible no se conectó usando el primer método, sin embargo, el Samsung Galaxy S y otro, no recuerdo cuál, se conectó en el primer intento. – TxAg

+0

Estaba plagado de esta excepción y esta solución parecía solucionar mis problemas. ¿Entiende lo que está sucediendo aquí y por qué alivia el problema de la falla del Servicio de Descubrimiento? – GobiasKoffi

2

Esto fue a suggested edit from an anonymous user intentando responder a la respuesta aceptada.

Una gran diferencia entre su código de antes y después es el UUID que está pasando. He encontrado mi respuesta aquí: http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createRfcommSocketToServiceRecord(java.util.UUID)

que tuvieron que reemplazar:

tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

con:

private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 
tmp = device.createRfcommSocketToServiceRecord(SPP_UUID); 

y listo funciona! El código original es para una aplicación de Android punto a punto. No tiene sentido utilizar el UUID de la aplicación cuando se conecta a un dispositivo Bluetooth de serie simple. Es por eso que el descubrimiento falla.

+0

Y ahora [otros comentarios anónimos de los usuarios] (http://stackoverflow.com/suggested-edits/335727): la edición sugerida está utilizando el mismo método exacto que el código que no funciona. El código de trabajo utiliza un método diferente no público que no requiere el uuid. – Rup

+0

Tiene el mismo error que el anterior al intentar escribir una aplicación de Android que se conecta a un escáner Bluetooth. Esta solución funcionó para mí. – zarazan

+0

Esto no tiene sentido. – Monsignor

13

A partir del API 15 se puede utilizar el siguiente método:

intente reemplazar su UUID con el valor de retorno del método getUuids() de la clase BluetoothDevice. lo que funcionó para mí fue algo como esto:

UUID uuid = bluetoothDevice.getUuids()[0].getUuid(); 
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid); 

La razón por la que esto funciona es que cada dispositivo admite distintos UUID y obteniendo los UUID del dispositivo mediante getUuids está apoyando todas las características y dispositivos.

Otro nuevo método interesante (compatible desde API 14) es este: BluetoothHealth.getConnectionState. No lo he probado, pero parece prometedor ...

1

Como se mencionó anteriormente, el punto es que debe usar el UUID que el servidor está esperando.

Si se está conectando a un dispositivo bluetooth, como un auricular o un mouse, debe verificar qué UUID está escuchando el dispositivo. Puedes ver los UUID así.

UUID[] uuids = bluetoothDevice.getUuids(); 

Y si quieres saber lo que significan estas UUID, ver this.

0

Esta es una realmente vieja pregunta, pero he encontrado que el uso de la createInsecureRfcommSocketToServiceRecord() en lugar de createRfcommSocketToServiceRecord() junto con el getUuids() se ha mencionado anteriormente hace el truco para mí

UUID uuid = bluetoothDevice.getUuids()[0].getUuid(); 
BluetoothSocket socket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid); 
Cuestiones relacionadas