La plataforma de Android incluye compatibilidad con la pila de red Bluetooth, que permite que un dispositivo intercambie datos de forma inalámbrica con otros dispositivos Bluetooth. El framework de la aplicación proporciona acceso a la funcionalidad de Bluetooth a través de las APIs de Bluetooth de Android. Estas APIs permiten que las aplicaciones se conecten de forma inalámbrica con otros dispositivos Bluetooth, lo que habilita las funciones inalámbricas punto a punto y de varios puntos.
Con las APIs de Bluetooth, una aplicación para Android puede realizar lo siguiente:
- Buscar otros dispositivos Bluetooth
- Consultar el adaptador local de Bluetooth en busca de dispositivos Bluetooth sincronizados
- Establecer canales RFCOMM
- Conectarse con otros dispositivos mediante el descubrimiento de servicios
- Transferir datos hacia otros dispositivos y desde estos
- Administrar varias conexiones
Esta página se enfoca en el Bluetooth clásico. El Bluetooth clásico es la opción ideal para las operaciones que consumen más batería, como la transmisión y la comunicación entre dispositivos Android. Para dispositivos Bluetooth con bajos requisitos de energía, Android 4.3 (nivel de API 18) presenta compatibilidad de API con Bluetooth de bajo consumo. Para obtener más información, consulta Bluetooth de bajo consumo.
En este documento, se describen diferentes perfiles de Bluetooth, incluido el perfil del dispositivo de salud. Luego, se explica cómo usar las APIs de Bluetooth de Android para realizar las cuatro tareas principales necesarias para comunicarse a través de Bluetooth: configurar Bluetooth, encontrar dispositivos que estén vinculados o disponibles en el área local, conectar dispositivos y transferir datos entre dispositivos.
Conceptos básicos
Para que los dispositivos con Bluetooth puedan transmitir datos entre sí, primero deben formar un canal de comunicación mediante un proceso de vinculación. Un dispositivo, un dispositivo detectable, se pone a disposición para las solicitudes de conexión entrantes. Otro dispositivo encuentra el dispositivo detectable mediante un proceso de descubrimiento de servicios. Después de que el dispositivo detectable acepta la solicitud de vinculación, los dos dispositivos completan un proceso de vinculación en el que intercambian llaves de seguridad. Ambos dispositivos almacenan estas claves en caché para usarlas posteriormente. Una vez que se completan los procesos de vinculación y vinculación, los dos dispositivos intercambian información. Cuando se completa la sesión, el dispositivo que inició la solicitud de vinculación libera el canal que lo había vinculado al dispositivo detectable. Sin embargo, los dos dispositivos permanecen vinculados para que puedan volver a conectarse automáticamente durante una sesión futura, siempre y cuando estén dentro del alcance entre sí y ninguno de los dispositivos haya eliminado la vinculación.
Permisos de Bluetooth
Para usar las funciones de Bluetooth en tu aplicación, debes declarar dos permisos. El primero es BLUETOOTH
.
Necesitas este permiso para realizar cualquier comunicación por Bluetooth, como solicitar una conexión, aceptar una conexión y transferir datos.
El otro permiso que debes declarar es ACCESS_FINE_LOCATION
.
Tu app necesita este permiso porque se puede usar una búsqueda de Bluetooth para recopilar información sobre la ubicación del usuario. Esta información puede provenir de los dispositivos del usuario o de las balizas Bluetooth que se usan en ubicaciones, como tiendas y centros de transporte público.
Los servicios que se ejecutan en Android 10 y versiones posteriores no pueden detectar dispositivos Bluetooth, a menos que tengan el permiso ACCESS_BACKGROUND_LOCATION
. Para obtener más información sobre este requisito, consulta Cómo acceder a la ubicación en segundo plano.
En el siguiente fragmento de código, se muestra cómo verificar el permiso.
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(baseContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_CODE) } }
Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(baseContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( MyActivity.this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, PERMISSION_CODE) } }
Una excepción a este requisito de permiso ocurre cuando la app se instala en un dispositivo con Android 11 o versiones posteriores, y usa la vinculación de dispositivos complementarios para asociar un dispositivo. En este caso, una vez que se asocia un dispositivo, las apps pueden buscar sus dispositivos Bluetooth asociados sin requerir un permiso de ubicación.
En los dispositivos que ejecutan Android 8.0 (nivel de API 26) y versiones posteriores, puedes usar CompanionDeviceManager
para realizar una búsqueda de dispositivos complementarios cercanos en nombre de tu app sin requerir el permiso de ubicación. Para obtener más información sobre esta opción, consulta Vinculación de dispositivos complementarios.
Nota: Si tu app se orienta a Android 9 (nivel de API 28) o versiones anteriores, puedes declarar el permiso ACCESS_COARSE_LOCATION
en lugar del permiso ACCESS_FINE_LOCATION
.
Si quieres que tu app inicie la detección de dispositivos o controle la configuración de Bluetooth, debes declarar los permisos BLUETOOTH_ADMIN
y BLUETOOTH
. La mayoría de las aplicaciones necesitan este permiso solamente para poder descubrir dispositivos Bluetooth locales. Las otras capacidades que otorga este permiso no deben usarse, a menos que la aplicación sea un "administrador de energía" que modifique la configuración de Bluetooth a pedido del usuario.
Declara los permisos de Bluetooth del archivo de manifiesto de tu aplicación. Por ejemplo:
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- If your app targets Android 9 or lower, you can declare ACCESS_COARSE_LOCATION instead. --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... </manifest>
Consulta la referencia <uses-permission> para obtener más información sobre cómo declarar permisos de la aplicación.
Trabajar con perfiles
A partir de Android 3.0, la API de Bluetooth incluye compatibilidad para trabajar con perfiles de Bluetooth. Un perfil de Bluetooth es una especificación de interfaz inalámbrica para la comunicación entre dispositivos basada en Bluetooth. Un ejemplo es el perfil de manos libres. Para que un teléfono celular se conecte a auriculares inalámbricos, ambos dispositivos deben admitir el perfil de manos libres.
La API de Bluetooth de Android proporciona implementaciones para los siguientes perfiles de Bluetooth:
- Auriculares. El perfil de auriculares ofrece compatibilidad con auriculares Bluetooth para usarlos con teléfonos móviles. Android proporciona la clase
BluetoothHeadset
, que es un proxy para controlar el servicio de auriculares Bluetooth. Esto incluye los perfiles de manos libres (v1.5) y de auriculares Bluetooth. La claseBluetoothHeadset
incluye compatibilidad con comandos de AT. Para obtener más información sobre este tema, consulta Comandos de AT específicos del proveedor. - A2DP: El perfil de distribución de audio avanzada (A2DP) define el nivel de audio de alta calidad que se puede transmitir de un dispositivo a otro a través de una conexión Bluetooth. Android proporciona la clase
BluetoothA2dp
, que es un proxy para controlar el servicio de A2DP Bluetooth. - Dispositivo de salud. Android 4.0 (nivel de API 14) incluye compatibilidad con el perfil de dispositivos de salud (HDP) Bluetooth. Esto te permite crear aplicaciones que usan Bluetooth para comunicarse con dispositivos de salud compatibles, como monitores de frecuencia cardíaca, medidores de la sangre, termómetros y balanzas, entre otros. Para obtener una lista de los dispositivos compatibles y sus códigos de especialización de datos del dispositivo correspondientes, consulta las especializaciones de datos de dispositivos del HDP de Bluetooth. También se hace referencia a estos valores en la especificación ISO/IEEE 11073-20601 [7] como MDC_DEV_SPEC_PROFILE_* en el anexo de códigos de nomenclatura. Para obtener más información sobre el HDP, consulta Perfil de dispositivos de salud.
A continuación, se detallan los pasos básicos para trabajar con un perfil:
- Obtén el adaptador predeterminado, como se describe en Cómo configurar Bluetooth.
- Configura un
BluetoothProfile.ServiceListener
. Este objeto de escucha notifica a los clientesBluetoothProfile
cuando se conectan al servicio o se desconectan de él. - Usa
getProfileProxy()
para establecer una conexión con el objeto del proxy de perfil asociado al perfil. En el siguiente ejemplo, el objeto del proxy de perfil es una instancia deBluetoothHeadset
. - En
onServiceConnected()
, obtén un handle para el objeto del proxy de perfil. - Una vez que tengas el objeto del proxy de perfil, puedes usarlo para supervisar el estado de la conexión y realizar otras operaciones relevantes para ese perfil.
Por ejemplo, en este fragmento de código, se muestra cómo conectarse a un objeto proxy BluetoothHeadset
para que puedas controlar el perfil de auriculares:
Kotlin
var bluetoothHeadset: BluetoothHeadset? = null // Get the default adapter val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() private val profileListener = object : BluetoothProfile.ServiceListener { override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = proxy as BluetoothHeadset } } override fun onServiceDisconnected(profile: Int) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = null } } } // Establish connection to the proxy. bluetoothAdapter?.getProfileProxy(context, profileListener, BluetoothProfile.HEADSET) // ... call functions on bluetoothHeadset // Close proxy connection after use. bluetoothAdapter?.closeProfileProxy(BluetoothProfile.HEADSET, bluetoothHeadset)
Java
BluetoothHeadset bluetoothHeadset; // Get the default adapter BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); private BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = (BluetoothHeadset) proxy; } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = null; } } }; // Establish connection to the proxy. bluetoothAdapter.getProfileProxy(context, profileListener, BluetoothProfile.HEADSET); // ... call functions on bluetoothHeadset // Close proxy connection after use. bluetoothAdapter.closeProfileProxy(bluetoothHeadset);
Comandos de AT específicos del proveedor
A partir de Android 3.0 (nivel de API 11), las aplicaciones pueden registrarse para recibir transmisiones del sistema de comandos de AT específicos del proveedor predefinidos que envían los auriculares (como un comando +XEVENT de Plantronics). Por ejemplo, una aplicación podría recibir transmisiones que indiquen el nivel de batería de un dispositivo conectado y notificar al usuario o tomar otras medidas, según sea necesario. Crea un receptor de emisión para el intent ACTION_VENDOR_SPECIFIC_HEADSET_EVENT
a fin de controlar los comandos de AT específicos del proveedor para los auriculares.
Perfil de dispositivos de salud
Android 4.0 (nivel de API 14) presenta compatibilidad con el perfil de dispositivos de salud (HDP) Bluetooth. Esto te permite crear aplicaciones que usan Bluetooth para comunicarse con dispositivos de salud compatibles con Bluetooth, como monitores de frecuencia cardíaca, medidores de la sangre, termómetros y balanzas. La API de Bluetooth Health incluye las clases BluetoothHealth
, BluetoothHealthCallback
y BluetoothHealthAppConfiguration
, que se describen en Interfaces y clases clave.
Cuando se usa la API de salud de Bluetooth, resulta útil comprender estos conceptos clave del HDP:
- Source
- Dispositivo de salud, como una báscula de peso, un glucosímetro o un termómetro, que transmite datos médicos a un dispositivo inteligente, como un teléfono o una tablet Android.
- Receptor
- Es el dispositivo inteligente que recibe los datos médicos. En una aplicación del HDP de Android, el receptor se representa con un objeto
BluetoothHealthAppConfiguration
. - Registro
- Es el proceso que se usa para registrar un receptor a fin de comunicarse con un dispositivo de salud específico.
- Conexión
- Es el proceso que se usa para abrir un canal entre un dispositivo de salud (fuente) y un dispositivo inteligente (receptor).
Crear una aplicación del HDP
Estos son los pasos básicos para crear una aplicación del HDP de Android:
- Obtén una referencia al objeto de proxy
BluetoothHealth
.Al igual que con los dispositivos de perfil A2DP y de auriculares normales, debes llamar a
getProfileProxy()
con unBluetoothProfile.ServiceListener
y el tipo de perfilHEALTH
para establecer una conexión con el objeto del proxy de perfil. - Crea un
BluetoothHealthCallback
y registra una configuración de la aplicación (BluetoothHealthAppConfiguration
) que actúe como receptor de estado. Establece una conexión con el dispositivo de salud.
Nota: Algunos dispositivos inician la conexión automáticamente. No es necesario seguir este paso en el caso de esos dispositivos.
- Cuando te conectes de forma correcta a un dispositivo de salud, realiza operaciones de lectura o escritura en el dispositivo de salud mediante el descriptor de archivo. Los datos recibidos deben interpretarse mediante un administrador de salud que implemente las especificaciones IEEE 11073.
- Cuando finalices, cierra el canal de salud y elimina el registro de la aplicación. El canal también se cierra cuando existe inactividad por tiempo prolongado.
Configurar el sistema Bluetooth
Antes de que tu aplicación pueda comunicarse a través de Bluetooth, debes verificar que Bluetooth sea compatible con el dispositivo y, de ser así, asegurarte de que esté habilitado.
Si Bluetooth no es compatible, debes inhabilitar correctamente cualquier función de Bluetooth. Si Bluetooth es compatible, pero está inhabilitado, puedes solicitar que el usuario lo habilite sin salir de tu aplicación. Esta configuración se realiza en dos pasos con BluetoothAdapter
:
- Obtén el
BluetoothAdapter
.Se requiere el
BluetoothAdapter
para toda la actividad Bluetooth. Para obtener elBluetoothAdapter
, llama al método estáticogetDefaultAdapter()
. Se mostrará unBluetoothAdapter
que representa el propio adaptador de Bluetooth del dispositivo (la radio Bluetooth). Existe un adaptador de Bluetooth para todo el sistema y tu aplicación puede interactuar con él usando este objeto. SigetDefaultAdapter()
muestranull
, significa que el dispositivo no es compatible con Bluetooth. Por ejemplo:Kotlin
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() if (bluetoothAdapter == null) { // Device doesn't support Bluetooth }
Java
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // Device doesn't support Bluetooth }
- Habilita Bluetooth.
A continuación, debes asegurarte de que Bluetooth esté habilitado. Llama a
isEnabled()
para verificar si Bluetooth está habilitado actualmente. Si este método muestra "false", Bluetooth está inhabilitado. Para solicitar que se habilite Bluetooth, llama astartActivityForResult()
y pasa una acción de intentACTION_REQUEST_ENABLE
. Esta llamada emite una solicitud para habilitar Bluetooth a través de la configuración del sistema (sin detener tu aplicación). Por ejemplo:Kotlin
if (bluetoothAdapter?.isEnabled == false) { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) }
Java
if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
Aparecerá un cuadro de diálogo en el que se le solicitará al usuario permiso para habilitar Bluetooth, como se muestra en la Figura 1. Si el usuario responde "Sí", el sistema comienza a habilitar Bluetooth y el enfoque regresa a tu aplicación una vez que se completa (o falla) el proceso.
Figura 1: Diálogo de habilitación de BluetoothLa constante
REQUEST_ENABLE_BT
que se pasa astartActivityForResult()
es un número entero definido localmente que debe ser mayor que 0. El sistema te devuelve esta constante en la implementación deonActivityResult()
como el parámetrorequestCode
.Si la habilitación de Bluetooth se realiza correctamente, tu actividad recibe el código de resultado
RESULT_OK
en la devolución de llamadaonActivityResult()
. Si Bluetooth no se habilitó debido a un error (o a que el usuario respondió "No"), el código de resultado seráRESULT_CANCELED
.
De manera opcional, tu aplicación también puede escuchar el intent de transmisión ACTION_STATE_CHANGED
, que el sistema emite cada vez que cambia el estado de Bluetooth. Esta transmisión incluye los campos adicionales EXTRA_STATE
y EXTRA_PREVIOUS_STATE
, que incluyen los estados de Bluetooth nuevo y antiguo, respectivamente. Los valores posibles para estos campos adicionales son STATE_TURNING_ON
, STATE_ON
, STATE_TURNING_OFF
y STATE_OFF
. La escucha de esta transmisión puede ser útil si tu app necesita detectar cambios en el tiempo de ejecución realizados en el estado de Bluetooth.
Nota: Cuando se habilita la visibilidad, se habilita Bluetooth automáticamente. Si planeas habilitar la visibilidad de dispositivos de manera constante antes de realizar la actividad de Bluetooth, puedes omitir el paso 2 anterior. Para obtener más información, consulta la sección Cómo habilitar la visibilidad en esta página.
Buscar dispositivos
Con el BluetoothAdapter
, puedes encontrar dispositivos Bluetooth remotos mediante la detección de dispositivos o consultando la lista de dispositivos vinculados.
La detección de dispositivos es un procedimiento de escaneo que busca dispositivos compatibles con Bluetooth en el área local y solicita información sobre cada uno. A veces, este proceso se denomina descubrimiento, consulta o análisis. Sin embargo, un dispositivo Bluetooth cercano responde a una solicitud de detección solo si actualmente acepta solicitudes de información por ser detectable. Si un dispositivo es detectable, comparte información como el nombre del dispositivo, su clase y su dirección MAC única como respuesta a la solicitud de descubrimiento. Con esta información, el dispositivo que realiza el proceso de descubrimiento puede elegir iniciar una conexión con el dispositivo detectado.
Como los dispositivos detectables pueden revelar información sobre la ubicación del usuario, el proceso de descubrimiento del dispositivo requiere acceso a la ubicación. Si la app se usa en un dispositivo con Android 8.0 (nivel de API 26) o una versión posterior, usa la API de Companion Device Manager. Esta API realiza el descubrimiento de dispositivos en nombre de tu app, por lo que esta no necesita solicitar permisos de ubicación.
Una vez que se establece una conexión con un dispositivo remoto por primera vez, se presenta automáticamente al usuario una solicitud de vinculación. Cuando se vincula un dispositivo, la información básica sobre este (como el nombre, la clase y la dirección MAC) se guarda y se puede leer con las APIs de Bluetooth. Usando la dirección MAC conocida de un dispositivo remoto, se puede establecer una conexión con este en cualquier momento sin llevar a cabo la detección, suponiendo que el dispositivo aún se encuentre dentro del rango.
Ten presente que existe una diferencia entre la vinculación y la conexión:
- Para estar vinculados, dos dispositivos conocen la existencia del otro, tienen una clave de vínculo compartida que se puede usar para la autenticación y son capaces de establecer una conexión encriptada entre sí.
- Para estar conectados, los dispositivos actualmente comparten un canal RFCOMM y pueden transmitir datos entre sí. Las API de Bluetooth de Android actuales requieren que los dispositivos estén vinculados para que se pueda establecer una conexión RFCOMM. La vinculación se realiza automáticamente cuando inicias una conexión encriptada con las APIs de Bluetooth.
En las siguientes secciones, se describe cómo encontrar dispositivos vinculados o nuevos con la detección de dispositivos.
Nota: Los dispositivos con Android no son detectables de forma predeterminada. Un usuario puede hacer que el dispositivo sea detectable durante un tiempo limitado a través de la configuración del sistema o una aplicación puede solicitar que el usuario habilite la visibilidad sin salir de la aplicación. Para obtener más información, consulta la sección Cómo habilitar la visibilidad en esta página.
Realizar consultas a dispositivos sincronizados
Antes de llevar a cabo la detección de dispositivos, es conveniente consultar el conjunto de dispositivos vinculados para ver si el dispositivo deseado ya es conocido. Para ello, llama a getBondedDevices()
. Se muestra un conjunto de objetos BluetoothDevice
que representan dispositivos vinculados. Por ejemplo, puedes consultar todos los dispositivos vinculados y obtener el nombre y la dirección MAC de cada uno, como se muestra en el siguiente fragmento de código:
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
Para iniciar una conexión con un dispositivo Bluetooth, todo lo que se necesita del objeto BluetoothDevice
asociado es la dirección MAC, que recuperas llamando a getAddress()
. Puedes obtener más información para crear una conexión en la sección Conexión de dispositivos.
Precaución: La detección de dispositivos consume muchos recursos del adaptador de Bluetooth. Después de encontrar un dispositivo al cual conectarte, asegúrate de detener la detección con cancelDiscovery()
antes de intentar establecer una conexión. Además, no debes realizar la detección mientras estás conectado a un dispositivo, ya que el proceso de descubrimiento reduce significativamente el ancho de banda disponible para las conexiones existentes.
Detectar dispositivos
Para comenzar a detectar dispositivos, simplemente llama a startDiscovery()
. El proceso es asíncrono y muestra un valor booleano que indica si el descubrimiento se inició de forma correcta. Por lo general, el proceso de descubrimiento implica un análisis de consulta de aproximadamente 12 segundos, seguido de un escaneo de la página de cada dispositivo encontrado para recuperar su nombre de Bluetooth.
A fin de recibir información sobre cada dispositivo detectado, tu aplicación debe registrar un BroadcastReceiver para el intent ACTION_FOUND
. El sistema transmite este intent por cada dispositivo. El intent contiene los campos adicionales EXTRA_DEVICE
y EXTRA_CLASS
, que, a su vez, contienen un BluetoothDevice
y un BluetoothClass
, respectivamente.
En el siguiente fragmento de código, se muestra cómo puedes registrarte para controlar la transmisión cuando se detectan los dispositivos:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
Para iniciar una conexión con un dispositivo Bluetooth, todo lo que se necesita del objeto BluetoothDevice
asociado es la dirección MAC, que recuperas llamando a getAddress()
. Puedes obtener más información para crear una conexión en la sección Conexión de dispositivos.
Precaución: La detección de dispositivos consume muchos recursos del adaptador de Bluetooth. Después de encontrar un dispositivo al cual conectarte, asegúrate de detener la detección con cancelDiscovery()
antes de intentar establecer una conexión. Además, no debes realizar la detección mientras estás conectado a un dispositivo, ya que el proceso de descubrimiento reduce significativamente el ancho de banda disponible para las conexiones existentes.
Habilitar la visibilidad
Si deseas que el dispositivo local sea detectable para otros dispositivos, llama a startActivityForResult(Intent, int)
con el intent ACTION_REQUEST_DISCOVERABLE
.
Esto emite una solicitud para habilitar el modo detectable del sistema sin tener que navegar a la app de Configuración, lo que detenería tu propia app. De forma predeterminada, el dispositivo se hace detectable durante 120 segundos o 2 minutos. Puedes definir una duración diferente, hasta 3,600 segundos (1 hora), si agregas el EXTRA_DISCOVERABLE_DURATION
adicional.
Precaución: Si estableces el valor adicional EXTRA_DISCOVERABLE_DURATION
en 0, el dispositivo siempre será detectable. Esta configuración no es segura y, por lo tanto, no se recomienda.
Con el siguiente fragmento de código, el dispositivo permanece detectable durante cinco minutos (300 segundos):
Kotlin
val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivity(discoverableIntent)
Java
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent);
Aparecerá un cuadro de diálogo en el que se solicitará permiso al usuario para que el dispositivo sea detectable, como se muestra en la Figura 2. Si el usuario responde "Sí", el dispositivo será detectable durante el período especificado. Luego, tu actividad recibe una llamada a la devolución de llamada onActivityResult()
, con un código de resultado igual a la duración durante la cual el dispositivo es detectable. Si el usuario respondió "No" o si se produjo un error, el código de resultado será RESULT_CANCELED
.
Nota: Si no se habilitó Bluetooth en el dispositivo, se habilitará Bluetooth automáticamente cuando se habilite la visibilidad de dispositivo.
El dispositivo se mantendrá silenciosamente en el modo detectable durante el tiempo asignado.
Si deseas recibir una notificación cuando cambie el modo detectable, puedes registrar un BroadcastReceiver para el intent ACTION_SCAN_MODE_CHANGED
. Este intent contiene los campos adicionales EXTRA_SCAN_MODE
y EXTRA_PREVIOUS_SCAN_MODE
, que proporcionan el modo de análisis nuevo y el antiguo, respectivamente. Estos son los posibles valores de cada campo adicional:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- El dispositivo está en modo detectable.
SCAN_MODE_CONNECTABLE
- El dispositivo no está en modo detectable, pero puede recibir conexiones de todos modos.
SCAN_MODE_NONE
- El dispositivo no está en modo detectable y no puede recibir conexiones.
Si inicias la conexión a un dispositivo remoto, no es necesario que habilites la visibilidad del dispositivo. Solo es necesario habilitar la visibilidad cuando quieres que tu aplicación aloje un socket de servidor que acepte conexiones entrantes, ya que los dispositivos remotos deben poder descubrir otros dispositivos antes de iniciar conexiones en ellos.
Conectar dispositivos
Para crear una conexión entre dos dispositivos, debes implementar los mecanismos del servidor y del cliente, ya que un dispositivo debe abrir un socket de servidor y el otro debe iniciar la conexión mediante la dirección MAC del dispositivo del servidor. El dispositivo del servidor y el dispositivo del cliente obtienen el BluetoothSocket
requerido de diferentes maneras. El servidor recibe la información del socket cuando se acepta una conexión entrante. El cliente proporciona información del socket cuando abre un canal RFCOMM al servidor.
El servidor y el cliente se consideran conectados entre sí cuando tienen un BluetoothSocket
conectado en el mismo canal RFCOMM. En este punto, cada dispositivo puede obtener flujos de entrada y salida, y se puede iniciar la transferencia de datos, lo que se analiza en la sección Cómo administrar una conexión. En esta sección, se describe cómo iniciar la conexión entre dos dispositivos.
Técnicas de conexión
Una técnica de implementación consiste en preparar automáticamente cada dispositivo como un servidor, de modo que cada uno tenga un socket de servidor abierto y escuche las conexiones. En este caso, cualquiera de los dispositivos puede iniciar una conexión con el otro y convertirse en cliente. Como alternativa, un dispositivo puede alojar explícitamente la conexión y abrir un socket de servidor a pedido, y el otro dispositivo inicia la conexión.
Nota: Si los dos dispositivos no se vincularon anteriormente, el framework de Android muestra automáticamente una notificación de solicitud de vinculación o un diálogo al usuario durante el procedimiento de conexión, como se muestra en la Figura 3. Por lo tanto, cuando tu aplicación intenta conectar dispositivos, no es necesario preocuparse por si los dispositivos están sincronizados o no. El intento de conexión RFCOMM se bloquea hasta que el usuario vincule correctamente los dos dispositivos, y falla si el usuario rechaza la vinculación, o si este proceso falla o se agota el tiempo de espera.
Conectarse como servidor
Cuando desees conectar dos dispositivos, uno deberá actuar como servidor y tener un BluetoothServerSocket
abierto. El propósito del socket de servidor es escuchar las solicitudes de conexión entrantes y proporcionar un BluetoothSocket
conectado cuando se acepta una solicitud. Cuando el BluetoothSocket
se adquiere del BluetoothServerSocket
, el BluetoothServerSocket
puede y debería descartarse, a menos que quieras que el dispositivo acepte más conexiones.
Para configurar un socket de servidor y aceptar una conexión, completa la siguiente secuencia de pasos:
- Llama a
listenUsingRfcommWithServiceRecord()
para obtener unBluetoothServerSocket
.La string es un nombre de identificación de tu servicio, que el sistema escribe automáticamente en una entrada nueva de la base de datos del protocolo de detección de servicios (SDP) en el dispositivo. El nombre es arbitrario y puede ser simplemente el de tu aplicación. El identificador único universal (UUID) también se incluye en la entrada del SDP y constituye la base del acuerdo de conexión con el dispositivo del cliente. Es decir, cuando el cliente intenta conectarse con este dispositivo, lleva un UUID que identifica de forma única el servicio con el que desea conectarse. Estos UUID deben coincidir para que se acepte la conexión.
Un UUID es un formato estandarizado de 128 bits para un ID de cadena que se usa con el objetivo de identificar información de manera única. La ventaja de un UUID es que es lo suficientemente grande como para que puedas seleccionar cualquier ID aleatorio y que no haya conflictos. En este caso, se usa para identificar de manera única el servicio Bluetooth de tu aplicación. A fin de obtener un UUID para usar con tu aplicación, puedes utilizar uno de los numerosos generadores de UUID aleatorios en la Web y, luego, inicializar un
UUID
confromString(String)
. - Llama a
accept()
para comenzar a detectar solicitudes de conexión.Esta es una llamada de bloqueo. Se muestra cuando se acepta una conexión o se produce una excepción. Una conexión se acepta solo cuando un dispositivo remoto envía una solicitud de conexión que contiene un UUID que coincide con el que se registró con este socket de servidor de escucha. Si se realiza de forma correcta,
accept()
muestra unBluetoothSocket
conectado. - A menos que desees aceptar conexiones adicionales, llama a
close()
.Este método libera el socket de servidor y todos sus recursos, pero no cierra el
BluetoothSocket
conectado que muestraaccept()
. A diferencia del TCP/IP, RFCOMM solo permite un cliente conectado por canal a la vez, por lo que en la mayoría de los casos, tiene sentido llamar aclose()
en elBluetoothServerSocket
inmediatamente después de aceptar un socket conectado.
Como la llamada a accept()
es de bloqueo, no se debe ejecutar en el subproceso de IU de la actividad principal para que tu aplicación pueda seguir respondiendo a otras interacciones del usuario. Por lo general, tiene sentido hacer todo el trabajo que involucra BluetoothServerSocket
o BluetoothSocket
en un subproceso nuevo que administra tu aplicación. Para anular una llamada bloqueada, como accept()
, llama a close()
en BluetoothServerSocket
o BluetoothSocket
desde otro subproceso. Ten en cuenta que todos los métodos en BluetoothServerSocket
o BluetoothSocket
cuentan con protección de subprocesos.
Ejemplo
A continuación, se muestra un subproceso simplificado para el componente de servidor que acepta conexiones entrantes:
Kotlin
private inner class AcceptThread : Thread() { private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) { bluetoothAdapter?.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID) } override fun run() { // Keep listening until exception occurs or a socket is returned. var shouldLoop = true while (shouldLoop) { val socket: BluetoothSocket? = try { mmServerSocket?.accept() } catch (e: IOException) { Log.e(TAG, "Socket's accept() method failed", e) shouldLoop = false null } socket?.also { manageMyConnectedSocket(it) mmServerSocket?.close() shouldLoop = false } } } // Closes the connect socket and causes the thread to finish. fun cancel() { try { mmServerSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } }
Java
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { // Use a temporary object that is later assigned to mmServerSocket // because mmServerSocket is final. BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code. tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's listen() method failed", e); } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned. while (true) { try { socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "Socket's accept() method failed", e); break; } if (socket != null) { // A connection was accepted. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket); mmServerSocket.close(); break; } } } // Closes the connect socket and causes the thread to finish. public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } }
En este ejemplo, solo se desea una conexión entrante, por lo que, apenas se acepta una conexión y se adquiere BluetoothSocket
, la app pasa el BluetoothSocket
adquirido a un subproceso independiente, cierra el BluetoothServerSocket
y sale del bucle.
Ten en cuenta que, cuando accept()
muestra el BluetoothSocket
, el socket ya está conectado. Por lo tanto, no debes llamar a connect()
, como lo haces del lado del cliente.
El método manageMyConnectedSocket()
específico de la app está diseñado para iniciar el subproceso de transferencia de datos, que se analiza en la sección Cómo administrar una conexión.
Por lo general, debes cerrar tu BluetoothServerSocket
en cuanto termines de escuchar las conexiones entrantes. En este ejemplo, se llama a close()
en cuanto se adquiere el objeto BluetoothSocket
. También te recomendamos que proporciones un método público en tu subproceso que pueda cerrar el BluetoothSocket
privado en caso de que necesites dejar de escuchar en ese socket de servidor.
Conectarse como cliente
Para iniciar una conexión con un dispositivo remoto que acepta conexiones en un socket de servidor abierto, primero debes obtener un objeto BluetoothDevice
que represente al dispositivo remoto.
Para obtener información sobre cómo crear un BluetoothDevice
, consulta Cómo buscar dispositivos. Luego, debes usar BluetoothDevice
para adquirir un BluetoothSocket
y, luego, iniciar la conexión.
El procedimiento básico es el siguiente:
- Con el
BluetoothDevice
, obtén unBluetoothSocket
llamando acreateRfcommSocketToServiceRecord(UUID)
.Este método inicializa un objeto
BluetoothSocket
que permite al cliente conectarse a unBluetoothDevice
. El UUID que se pasa aquí debe coincidir con el que usó el dispositivo del servidor cuando llamó alistenUsingRfcommWithServiceRecord(String, UUID)
para abrir suBluetoothServerSocket
. Para usar un UUID que coincida, codifica la string del UUID en tu aplicación y, luego, haz referencia a ella desde el código del servidor y del cliente. - Para iniciar la conexión, llama a
connect()
. Ten presente que este método es una llamada de bloqueo.Después de que un cliente llama a este método, el sistema realiza una búsqueda del SDP para encontrar el dispositivo remoto con el UUID que coincide. Si la búsqueda se realiza correctamente y el dispositivo remoto acepta la conexión, este comparte el canal RFCOMM que se usará durante la conexión, y se muestra el método
connect()
. Si la conexión falla o si se agota el tiempo de espera del métodoconnect()
(después de unos 12 segundos), el método arroja unaIOException
.Como
connect()
es una llamada de bloqueo, siempre debes realizar este procedimiento de conexión en un subproceso independiente del subproceso de la IU de la actividad principal.Nota: Siempre debes llamar a
cancelDiscovery()
para asegurarte de que el dispositivo no esté realizando la detección de dispositivos antes de llamar aconnect()
. Si el descubrimiento está en curso, el intento de conexión se ralentiza considerablemente y es más probable que falle.
Ejemplo
A continuación, se muestra un ejemplo básico de un subproceso de cliente que inicia una conexión Bluetooth:
Kotlin
private inner class ConnectThread(device: BluetoothDevice) : Thread() { private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { device.createRfcommSocketToServiceRecord(MY_UUID) } public override fun run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter?.cancelDiscovery() mmSocket?.use { socket -> // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. socket.connect() // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket) } } // Closes the client socket and causes the thread to finish. fun cancel() { try { mmSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the client socket", e) } } }
Java
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket // because mmSocket is final. BluetoothSocket tmp = null; mmDevice = device; try { // Get a BluetoothSocket to connect with the given BluetoothDevice. // MY_UUID is the app's UUID string, also used in the server code. tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's create() method failed", e); } mmSocket = tmp; } public void run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter.cancelDiscovery(); try { // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and return. try { mmSocket.close(); } catch (IOException closeException) { Log.e(TAG, "Could not close the client socket", closeException); } return; } // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(mmSocket); } // Closes the client socket and causes the thread to finish. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the client socket", e); } } }
Ten en cuenta que, en este fragmento, se llama a cancelDiscovery()
antes de que se produzca el intento de conexión. Siempre debes llamar a cancelDiscovery()
antes de connect()
, especialmente porque cancelDiscovery()
funciona correctamente independientemente de si el descubrimiento del dispositivo está en curso o no. Sin embargo, si tu app necesita determinar si el descubrimiento de dispositivos está en curso, puedes verificarlo con isDiscovering()
.
El método manageMyConnectedSocket()
específico de la app está diseñado para iniciar el subproceso de transferencia de datos, que se analiza en la sección Cómo administrar una conexión.
Cuando termines con BluetoothSocket
, siempre llama a close()
. Cuando lo hagas, se cerrará de inmediato el socket conectado y se liberarán todos los recursos internos relacionados.
Administrar una conexión
Después de conectar correctamente varios dispositivos, cada uno tiene un BluetoothSocket
conectado. Aquí es donde comienza la diversión porque puedes compartir información entre dispositivos. Con BluetoothSocket
, el procedimiento general para transferir datos es el siguiente:
- Obtén el
InputStream
y elOutputStream
que controlan las transmisiones a través del socket mediantegetInputStream()
ygetOutputStream()
, respectivamente. - Lee y escribe datos en las transmisiones con
read(byte[])
ywrite(byte[])
.
Por supuesto, existen detalles relacionados con la implementación que deben tenerse en cuenta. En particular, debes usar un subproceso dedicado para leer desde la transmisión y escribir en ella. Esto es importante porque los métodos read(byte[])
y write(byte[])
son llamadas de bloqueo. El método read(byte[])
se bloquea hasta que haya algo que leer de la transmisión. Por lo general, el método write(byte[])
no realiza el bloqueo, pero sí puede bloquearlo para el control del flujo si el dispositivo remoto no llama a read(byte[])
lo suficientemente rápido y, como resultado, se llenan los búferes intermedios.
Por lo tanto, el bucle principal del subproceso debe dedicarse a leer desde InputStream
. Se puede usar un método público separado en el subproceso para iniciar operaciones de escritura en OutputStream
.
Ejemplo
Este es un ejemplo de cómo puedes transferir datos entre dos dispositivos conectados a través de Bluetooth:
Kotlin
private const val TAG = "MY_APP_DEBUG_TAG" // Defines several constants used when transmitting messages between the // service and the UI. const val MESSAGE_READ: Int = 0 const val MESSAGE_WRITE: Int = 1 const val MESSAGE_TOAST: Int = 2 // ... (Add other message types here as needed.) class MyBluetoothService( // handler that gets info from Bluetooth service private val handler: Handler) { private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() { private val mmInStream: InputStream = mmSocket.inputStream private val mmOutStream: OutputStream = mmSocket.outputStream private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream override fun run() { var numBytes: Int // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) { // Read from the InputStream. numBytes = try { mmInStream.read(mmBuffer) } catch (e: IOException) { Log.d(TAG, "Input stream was disconnected", e) break } // Send the obtained bytes to the UI activity. val readMsg = handler.obtainMessage( MESSAGE_READ, numBytes, -1, mmBuffer) readMsg.sendToTarget() } } // Call this from the main activity to send data to the remote device. fun write(bytes: ByteArray) { try { mmOutStream.write(bytes) } catch (e: IOException) { Log.e(TAG, "Error occurred when sending data", e) // Send a failure message back to the activity. val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST) val bundle = Bundle().apply { putString("toast", "Couldn't send data to the other device") } writeErrorMsg.data = bundle handler.sendMessage(writeErrorMsg) return } // Share the sent message with the UI activity. val writtenMsg = handler.obtainMessage( MESSAGE_WRITE, -1, -1, bytes) writtenMsg.sendToTarget() } // Call this method from the main activity to shut down the connection. fun cancel() { try { mmSocket.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } } }
Java
public class MyBluetoothService { private static final String TAG = "MY_APP_DEBUG_TAG"; private Handler handler; // handler that gets info from Bluetooth service // Defines several constants used when transmitting messages between the // service and the UI. private interface MessageConstants { public static final int MESSAGE_READ = 0; public static final int MESSAGE_WRITE = 1; public static final int MESSAGE_TOAST = 2; // ... (Add other message types here as needed.) } private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private byte[] mmBuffer; // mmBuffer store for the stream public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams; using temp objects because // member streams are final. try { tmpIn = socket.getInputStream(); } catch (IOException e) { Log.e(TAG, "Error occurred when creating input stream", e); } try { tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "Error occurred when creating output stream", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { mmBuffer = new byte[1024]; int numBytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) { try { // Read from the InputStream. numBytes = mmInStream.read(mmBuffer); // Send the obtained bytes to the UI activity. Message readMsg = handler.obtainMessage( MessageConstants.MESSAGE_READ, numBytes, -1, mmBuffer); readMsg.sendToTarget(); } catch (IOException e) { Log.d(TAG, "Input stream was disconnected", e); break; } } } // Call this from the main activity to send data to the remote device. public void write(byte[] bytes) { try { mmOutStream.write(bytes); // Share the sent message with the UI activity. Message writtenMsg = handler.obtainMessage( MessageConstants.MESSAGE_WRITE, -1, -1, bytes); writtenMsg.sendToTarget(); } catch (IOException e) { Log.e(TAG, "Error occurred when sending data", e); // Send a failure message back to the activity. Message writeErrorMsg = handler.obtainMessage(MessageConstants.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString("toast", "Couldn't send data to the other device"); writeErrorMsg.setData(bundle); handler.sendMessage(writeErrorMsg); } } // Call this method from the main activity to shut down the connection. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } } }
Después de que el constructor obtiene las transmisiones necesarias, el subproceso espera a que los datos lleguen a través de InputStream
. Cuando read(byte[])
muestra datos de la transmisión, estos se envían a la actividad principal mediante un miembro Handler
de la clase superior. Luego, el subproceso espera a que se lean más bytes del InputStream
.
El envío de datos salientes solo implica llamar al método write()
del subproceso desde la actividad principal y pasar los bytes que se enviarán. Este método llama a write(byte[])
para enviar los datos al dispositivo remoto. Si se arroja una IOException
cuando se llama a write(byte[])
, el subproceso envía un aviso a la actividad principal y le explica al usuario que el dispositivo no pudo enviar los bytes dados al otro dispositivo (conectado).
El método cancel()
del subproceso permite finalizar la conexión en cualquier momento cuando cierras BluetoothSocket
.
Siempre debes llamar a este método cuando dejes de usar la conexión Bluetooth.
Para ver una demostración de cómo usar las APIs de Bluetooth, consulta la app de ejemplo de Chat de Bluetooth.
Clases fundamentales e interfaces
Todas las APIs de Bluetooth están disponibles en el paquete android.bluetooth
. A continuación, se muestra un resumen de las clases e interfaces que necesitas para crear conexiones Bluetooth:
BluetoothAdapter
- Representa el adaptador local de Bluetooth (radio Bluetooth). El
BluetoothAdapter
es el punto de entrada de toda la interacción de Bluetooth. Con esto, puedes descubrir otros dispositivos Bluetooth, consultar una lista de dispositivos vinculados (vinculados), crear una instancia deBluetoothDevice
con una dirección MAC conocida y crear unBluetoothServerSocket
para escuchar las comunicaciones de otros dispositivos. BluetoothDevice
- Representa un dispositivo Bluetooth remoto. Úsalo para solicitar una conexión con un dispositivo remoto a través de un
BluetoothSocket
o consultar información sobre el dispositivo, como su nombre, dirección, clase y estado de vinculación. BluetoothSocket
- Representa la interfaz de un socket Bluetooth (similar a un
Socket
de TCP). Este es el punto de conexión que permite que una aplicación intercambie datos con otro dispositivo Bluetooth medianteInputStream
yOutputStream
. BluetoothServerSocket
- Representa un socket de servidor abierto que escucha las solicitudes entrantes (similar a un
ServerSocket
de TCP). Para conectar dos dispositivos Android, un dispositivo debe abrir un socket de servidor con esta clase. Cuando un dispositivo Bluetooth remoto envía una solicitud de conexión a este dispositivo, este la acepta y muestra unBluetoothSocket
conectado. BluetoothClass
- Describe las características y capacidades generales de un dispositivo Bluetooth. Se trata de un conjunto de propiedades de solo lectura que define las clases y los servicios del dispositivo. Si bien esta información brinda una sugerencia útil sobre el tipo de dispositivo, los atributos de esta clase no necesariamente describen todos los perfiles y servicios de Bluetooth que admite el dispositivo.
BluetoothProfile
- Interfaz que representa un perfil de Bluetooth. Un perfil de Bluetooth es una especificación de interfaz inalámbrica para la comunicación entre dispositivos basada en Bluetooth. Un ejemplo es el perfil de manos libres. Para obtener más información sobre los perfiles, consulta Trabaja con perfiles.
BluetoothHeadset
- Proporciona compatibilidad para usar auriculares Bluetooth con teléfonos móviles. Esto incluye el perfil de auriculares Bluetooth y el perfil de manos libres (v1.5).
BluetoothA2dp
- Define cómo se puede transmitir audio de alta calidad de un dispositivo a otro mediante una conexión Bluetooth mediante el perfil de distribución de audio avanzada (A2DP).
BluetoothHealth
- : Representa un proxy de perfil de dispositivos de salud que controla el servicio Bluetooth.
BluetoothHealthCallback
- Es una clase abstracta que se usa para implementar devoluciones de llamada de
BluetoothHealth
. Debes extender esta clase e implementar los métodos de devolución de llamada para recibir actualizaciones sobre los cambios en el estado de registro de la aplicación y el estado del canal de Bluetooth. BluetoothHealthAppConfiguration
- Representa una configuración de la aplicación que la aplicación de terceros de salud de Bluetooth registra para comunicarse con un dispositivo de salud Bluetooth remoto.
BluetoothProfile.ServiceListener
- Una interfaz que notifica a los clientes de comunicación entre procesos (IPC) de
BluetoothProfile
cuando se conectan al servicio interno que ejecuta un perfil en particular o se desconectan de él.