====== Android i Bluetooth ====== El tema de Bluetooth és ample i complex. En aquest article abordarem el codi necessari per: * Gestionar els **permisos per a comunicació Bluetooth**. * Llistar i triar entre els **dispositius aparellats** al sistema operatiu. * Utilitzar **GATT per a recepció de dades** entre dispositius BLE o Bluetooth Low Emission. {{ android-bluetooth.jpg?400 }} Altres temes pendents d'abordar aquí: * Escaneig de dispositius. * GATT per a la transmissió de dades. La pràctica que s'inclou aquí està pensada per a rebre dades d'un dispositiu [[ESP32]]. Podeu trobar [[esp32|aquí la pràctica de captura amb càmera i transmissió de dades per BLE]]. {{tag> #Dam #DamMp08 #DamMp08Uf2 #DamMp08Uf02 Android mobile kotlin bluetooth BLE BT }} \\ ===== Llistar els dispositius emparellats ===== Obtenir aquesta llista és senzill accedint ''BluetoothAdapter.bondedDevices''. En aquest exemple, a més, filtrem els dispositius que poden ser del tipus BLE (Bluetooth Low Emission), però es pot treure el filtre si cal: @SuppressLint("MissingPermission") fun updatePairedDevices() { // empty list dataset.clear() // update list val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager val bluetoothAdapter = bluetoothManager.adapter for( elem in bluetoothAdapter.bondedDevices.filter { device -> // Filtrar per dispositius BLE device.type == BluetoothDevice.DEVICE_TYPE_LE || device.type == BluetoothDevice.DEVICE_TYPE_DUAL || device.type == BluetoothDevice.DEVICE_TYPE_UNKNOWN } ) { // afegim element al dataset dataset.add( elem ) } } \\ ===== Gestió de permisos ===== La gestió de permisos del Bluetooth és una part més engorrosa. Primer de tot, declarar els permisos estàtics a ''AndroidManifest.xml'': Seguidament, necessitarem al nostre codi demanar els permisos dinàmics. Abans de cridar a la funció ''updatePairedDevices()'' ja vista abans, haurem de fer una funció "wrapper" que abans s'asseguri que els permisos estan ben gestionats. private val REQUEST_CODE_BLUETOOTH = 100 // es pot posar un nombre aleatori no emprat en cap altre lloc private fun requestBluetoothPermissionAndUpdate() { val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+ requereix BLUETOOTH_CONNECT Manifest.permission.BLUETOOTH_CONNECT } else { // Versions anteriors Manifest.permission.BLUETOOTH } if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) { // Demanar el permís ActivityCompat.requestPermissions( this, arrayOf(permission), REQUEST_CODE_BLUETOOTH ) } else { // Permís ja concedit - llegir dispositius updatePairedDevices() } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_CODE_BLUETOOTH) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permís concedit - llegir dispositius updatePairedDevices() } else { // Permís denegat Toast.makeText(this, "Permís necessari per a llegir Bluetooth", Toast.LENGTH_SHORT).show() } } } \\ ===== Rebre fotos amb BLE GATT : BLEconnDialog ===== Per la comunicació de dades (sèrie) es sol utilitzar el **Bluetooth GATT o Generic Attribute Profile**. GATT és un protocol de serveis i característiques que defineix com s'intercanvien dades entre dispositius Bluetooth Low Energy (BLE). És la base de tota comunicació en dispositius BLE com ara wearables, sensors mèdics, beacons, etc. GATT és essencial per a l'ecosistema IoT i dispositius wearables, permetent una comunicació estructurada i eficient entre dispositius. Conceptes claus: * **Profile**: Especificació estàndard (ex: Perfil de freqüència cardíaca) * **Service**: Col·lecció de característiques relacionades (ex: "Servei de freqüència cardíaca") * **Characteristic**: Conté una dada específica (ex: "Mesura de freqüència cardíaca") * **Descriptor**: Metadades sobre les característiques Us presento un codi per recepció de dades BLE encapsulat dins un ''Dialog'', per tal d'efectuar la recepció de les dades i tancar la comunicació, i tot dins d'un arxiu separat del codi de l'''Activity'' o ''Fragment''. El ''BLEconnDialog'' no gestiona els permisos, assumim que ja s'ha fet abans en el codi per accedir al llistat de dispositius emparellats o fent un //scan//. \\ ==== Layout Dialog ==== El //layout// conté diversos ''TextView'' per a l'estat de la comunicació, una ''ProgressBar'' pel progrés de la transmissió i una ''ImageView'' per mostrar la imatge rebuda (que també s'enregistrarà al sistema d'arxius del mòbil).