Cómo conectar un dispositivo Android a un dispositivo iOS a través de BLE (Bluetooth Low Energy)

82

Estoy intentando crear una aplicación que utilice la nueva API de Bluetooth Low Energy de Android. Para esto, comencé con la muestra BLE que viene con API nivel 18 .

Cuando leí que Android no puede actuar como un periférico, puse el teléfono Android en modo central, buscando dispositivos BLE a su alrededor. Para ello, realicé algunas pruebas con una plataforma nórdica simulando un sensor cardíaco. ¡Todo funciona a la perfección!

Después de esto, trato de coger un iPhone (iOS 7 beta 4) y ponerlo de forma periférica y simulando un sensor de frecuencia cardíaca como la prueba anterior. La aplicación de Android puede ver el dispositivo y conectarse a él. Pero una vez que la conexión está activa, los 2 dispositivos se desconectan entre sí en 3-4 segundos. Además de eso, cuando llamo a discoverServices () en el lado de Android, ¡no se activa ninguna devolución de llamada! En algunos casos, el dispositivo Android recibe el evento "Conectado" incluso si el chip Bluetooth de iOS está apagado. Esto es muy extraño. Para demostrarlo, puse el Nordic Board en modo Central y pude conectarme correctamente al dispositivo iOS sin problemas.

¿Qué podría ser? ¿Existen algunas limitaciones en Android o iOS que no permiten conectarse de un Android a un iOS o viceversa?

Gracias.

EDITAR: Después de algunas pruebas duras, planteé un problema en la página de AOSP. Se puede consultar aquí

edoardotognoni
fuente
2
Según la documentación, Android SÍ admite la ejecución como servidor (por ejemplo, un monitor de frecuencia cardíaca), aunque los valores que uno genera serán falsos. Por otro lado, no hay ejemplos, la documentación le dice que haga cosas incorrectas y no hay forma de iniciar anuncios (aunque la documentación dice que puede).
Brian Reinhold
Tienes razón. Ya encontré el error de documentación sobre BluetoothGattServer. No puede tener la instancia de GattServer con el método getProfileProxy (como dice el documento), pero puede hacerlo desde BluetoothManager.openGattServer (). Ya se informó a Google como un problema. De todos modos, sí, Android puede actuar como un GattServer pero no puede hacer publicidad. Si te puede interesar, ya lo he probado y luego de la conexión de los 2 dispositivos, el control remoto puede ver los servidores Gatt expuestos desde Android. Consulte los comentarios de la primera respuesta para ver mi informe de problemas sobre esta pregunta.
edoardotognoni
Sí, también me topé con eso y agregué mis dos centavos a ese problema. Ahora tengo un servidor de termómetro que no puede anunciar, así que no puedo usarlo.
Brian Reinhold
Abrí un hilo casi idéntico al tuyo: stackoverflow.com/questions/18410081/… Observaré este hilo para ver las soluciones que encuentres.
afrederick
Lea el problema de Android que publiqué en la sección EDITAR de la pregunta. Explica claramente por qué este proceso está fallando. creemos que es una falla de Android. Principalmente es enviar un mensaje no permitido a través de un canal BLE fijo. Creo que lo único que podemos hacer es esperar un nuevo lanzamiento de Android :(
edoardotognoni

Respuestas:

7

Agregar un resumen como referencia:

¿Qué podría ser? ¿Existen algunas limitaciones en Android o iOS que no permiten conectarse de un Android a un iOS o viceversa?

Cuando se conecta a un servidor GATT que se anuncia como dispositivo de modo dual (BLE y BR / EDR) llamando a connectGatt (...), la marca TRANSPORT_AUTO que se agrega internamente hace que Android tenga por defecto el modo BR / EDR ( enlace ).

Son posibles las siguientes soluciones:

  1. Lado periférico: Detenga la publicidad de las capacidades BR / EDR ajustando las banderas apropiadas ( enlace )
  2. Lado central: establezca el parámetro de transporte explícitamente en TRANSPORT_LE llamando a la versión oculta de connectGatt () usando la reflexión

Ejemplo:

public void connectToGatt(BluetoothDevice device) {    
   ...    
   Method m = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);    
   int transport = device.getClass().getDeclaredField("TRANSPORT_LE").getInt(null);     // LE = 2, BREDR = 1, AUTO = 0    
   BluetoothGatt mGatt = (BluetoothGatt) m.invoke(device, this, false, gattCallback, transport);    
   ... 
}

Editar 4/2016

Como Arbel israelí señaló en el comentario, Google presentó una versión sobrecargada de connectGatt (...) lo que permite especificar el transporte en Android M .

Dominik Gebhart
fuente
Gracias, eso funciona para mí, tenga en cuenta que en Android M, Google ha agregado una sobrecarga para el método connectGatt que toma una variable de transporte: connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback, int transport)
arbel03
1
Oh, gracias por esta pista, así que finalmente la hicieron disponible.
Dominik Gebhart
2

Escribí un ejemplo de trabajo simple, relativamente simple, y lo incluí de código abierto en Github: https://github.com/GitGarage . Hasta ahora solo se ha probado con un Android Nexus 9 y un iPhone 5s, pero supongo que también funcionaría con un Nexus 6 y varios tipos de iPhone. Hasta ahora está configurado explícitamente para comunicarse entre un Android y un iPhone, pero supongo que se puede modificar para hacer mucho más.

omikes
fuente
2

Quizás un poco retrasado, pero quizás su dolor pueda aliviarse un poco;)

Hemos estado experimentando mucho con conexiones BLE multiplataforma (iOS <-> Android) y aprendimos que todavía existen muchas incompatibilidades y problemas de conexión. Aparte de la inestabilidad de Android, también debe considerar que todavía, a día de hoy, no muchos dispositivos Android son compatibles con el modo BLE Peripheral.

Por lo tanto, si su caso de uso se basa en funciones y solo necesita un intercambio de datos básico, le sugiero que mire los marcos y bibliotecas que pueden lograr la comunicación entre plataformas para usted, sin necesidad de crearla desde cero.

Por ejemplo: http://p2pkit.io o google cercano

Descargo de responsabilidad: trabajo para Uepaa, desarrollando p2pkit.io para Android e iOS.

p2pkit
fuente
1

Ahora puede pasar a TRANSPORT_LEtravés BluetoothDevice.connectGattde API 23.

Consulte las referencias de la documentación de Android a continuación:

Kevin Crain
fuente
0

Los dispositivos iOS siempre serán periféricos o centrales, pero los dispositivos Android no pueden serlo raras veces. En este caso, tu dispositivo iOS debe ser un periférico y Android debe ser una central. Podemos pensar que el periférico es un servidor y la central es un cliente. Esto es simple.

Mustafa Demir
fuente