BluetoothLeScanner — ce este, metode și scanare BLE în Android

Autor: IT Sectr Publicat: 2026-07-16 Timp de citire: 10 min

BluetoothLeScanner — clasa Android pentru scanarea dispozitivelor Bluetooth Low Energy, disponibilă începând cu API 21 (Android 5.0). BluetoothLeScanner a înlocuit metoda învechită startLeScan de pe BluetoothAdapter, oferind o API flexibilă cu configurare a scanării (ScanSettings), filtrare (ScanFilter) și suport pentru modul fundal (PendingIntent). Instanța se obține prin BluetoothAdapter.getBluetoothLeScanner(). Potrivit Android Developers, 2026, BluetoothLeScanner suportă trei moduri de consum energetic și permite scanarea pachetelor publicitare BLE cu filtrare după UUID serviciu, nume dispozitiv sau adresă MAC.

Principalele

  • BluetoothLeScanner — API modern Android (API 21+) pentru scanare BLE, înlocuind startLeScan învechit
  • ScanSettings — configurarea modului de scanare: LOW_POWER, BALANCED, LOW_LATENCY și tip callback
  • ScanFilter — filtrarea rezultatelor după UUID serviciu, nume dispozitiv, adresă MAC, date producător
  • ScanCallback — callback rezultate onScanResult, onBatchScanResults și onScanFailed cu coduri de eroare
  • PendingIntent — scanare în fundal prin BroadcastReceiver, chiar când aplicația este în fundal

Ce este BluetoothLeScanner: esența și obținerea instanței

BluetoothLeScanner — clasa de sistem pentru gestionarea scanării BLE pe Android. Spre deosebire de BluetoothAdapter.startLeScan(), care primește un simplu callback LeScanCallback, BluetoothLeScanner oferă o API orientată pe obiecte cu setări, filtre și gestionare extinsă a erorilor. Clasa a apărut în API 21 (Android 5.0) odată cu suportul BLE 4.2 și rămâne principala metodă de scanare BLE pe toate versiunile moderne de Android.

Obținerea instanței BluetoothLeScanner se realizează prin BluetoothAdapter.getBluetoothLeScanner(). Metoda returnează null dacă adaptorul Bluetooth este indisponibil (Bluetooth dezactivat sau dispozitivul nu suportă BLE). Înainte de obținere, verificați BluetoothAdapter.isEnabled() și prezența FEATURE_BLUETOOTH_LE prin PackageManager. După obținerea scanerului, puteți porni scanarea în orice thread — Android planifică el însuși operațiile BLE pe threadul intern al stivei Bluetooth.

kotlin
// Obținerea BluetoothLeScanner
class BLEScannerManager(context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    private val adapter: BluetoothAdapter? = bluetoothManager.adapter
    private var scanner: BluetoothLeScanner? = null

    fun initScanner(): Boolean {
        // Verificați disponibilitatea BLE
        if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
            return false
        }

        // Verificați Bluetooth activat
        if (adapter?.isEnabled != true) {
            return false
        }

        // Obțineți scanerul
        scanner = adapter?.bluetoothLeScanner
        return scanner != null
    }

    // Verificați disponibilitatea scanerului
    val isAvailable: Boolean
        get() = scanner != null

    // Porniți scanarea de bază fără filtre
    fun startBasicScan() {
        scanner?.startScan(object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                handleResult(result)
            }
        })
    }

    private fun handleResult(result: ScanResult) {
        val device = result.device
        print("Device: ${device.name ?: "Unnamed"}, RSSI: ${result.rssi}, address: ${device.address}")
    }
}

Clasa BLEScannerManager demonstrează obținerea și inițializarea sigură a BluetoothLeScanner. initScanner verifică prezența BLE prin hasSystemFeature, Bluetooth activat și obținerea cu succes a scanerului. startBasicScan pornește scanarea fără setări și filtre — detectează toate dispozitivele BLE în raza de acțiune. handleResult analizează ScanResult: BluetoothDevice (nume, adresă), RSSI (nivel semnal), scanRecord (date publicitare).

ScanSettings: moduri de scanare și tip callback

ScanSettings — clasa pentru configurarea scanării BLE. Parametrul principal — modul de scanare (scanMode), care determină compromisul între consumul de energie și întârzierea detectării. ScanSettings.Builder permite configurarea: scanMode, callbackType (CALLBACK_TYPE_ALL_MATCHES, CALLBACK_TYPE_FIRST_MATCH, CALLBACK_TYPE_MATCH_LOST), matchMode (MATCH_MODE_AGGRESSIVE, MATCH_MODE_STICKY), reportDelay (întârziere trimitere lot) și phy (PHY_LE_1M, PHY_LE_2M, PHY_LE_CODED).

Trei moduri de scanare: SCAN_MODE_LOW_POWER (0) — scanare în fundal cu consum redus de energie, întârziere detectare câteva secunde. SCAN_MODE_BALANCED (1) — mod echilibrat pentru majoritatea scenariilor. SCAN_MODE_LOW_LATENCY (2) — întârziere minimă de detectare (aproximativ 100 ms), consum maxim de energie. Pentru căutarea activă a dispozitivelor utilizați LOW_LATENCY, pentru monitorizare în fundal — LOW_POWER.

reportDelay — întârzierea în milisecunde înainte de trimiterea în grup a rezultatelor. Dacă reportDelay = 0, rezultatele sunt trimise imediat după detectare. Dacă > 0, Android acumulează rezultatele și trimite lotul prin onBatchScanResults. Trimiterea în loturi reduce numărul de apeluri callback și consumul de energie, fiind potrivită pentru scanarea în fundal cu prioritate scăzută.

kotlin
// Configurarea ScanSettings pentru diferite scenarii
class ScanSettingsProvider {

    // 1. Scanare rapidă (căutare activă)
    fun lowLatencyScan(): ScanSettings {
        return ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
            .setReportDelay(0)
            .setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED)
            .build()
    }

    // 2. Scanare eficientă energetic (monitorizare fundal)
    fun lowPowerScan(): ScanSettings {
        return ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
            .setMatchMode(ScanSettings.MATCH_MODE_STICKY)
            .setReportDelay(2000)  // lot la fiecare 2 secunde
            .build()
    }

    // 3. Scanare BLE Long Range (Coded PHY)
    fun longRangeScan(): ScanSettings {
        return ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setPhy(ScanSettings.PHY_LE_CODED)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .build()
    }

    // 4. Scanare doar pe 2M PHY (BLE 5.0+)
    fun highSpeedScan(): ScanSettings {
        return ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setPhy(ScanSettings.PHY_LE_2M)
            .build()
    }
}

Clasa ScanSettingsProvider conține configurații tipice. lowLatencyScan — pentru scanare UI (căutare „aici și acum”). lowPowerScan — pentru monitorizare în fundal cu lot la fiecare 2 secunde și callbackType FIRST_MATCH (se declanșează doar la prima detectare). longRangeScan folosește PHY_LE_CODED (BLE Long Range, până la 1 km). highSpeedScan — PHY_LE_2M (2 Mbit/s, doar dispozitive BLE 5.0+).

ScanFilter: filtrarea dispozitivelor BLE după UUID și nume

ScanFilter — clasa pentru filtrarea rezultatelor scanării BLE. Fără filtru, BluetoothLeScanner returnează toate dispozitivele BLE în raza de acțiune — într-un mediu BLE dens, aceasta înseamnă sute de pachete pe minut. ScanFilter restrânge rezultatele la dispozitivele necesare, reducând consumul de energie și încărcarea aplicației. Filtrele sunt aplicate la nivelul stivei Bluetooth — pachetele nepotrivite sunt respinse înainte de livrarea către aplicație.

Tipuri de filtre: setServiceUuid — UUID serviciu (obligatoriu format 128-bit complet). setDeviceName — subșir al numelui dispozitivului (sensibil la majuscule, potrivire exactă a subșirului). setDeviceAddress — adresă MAC exactă. setManufacturerData — date producător (ID companie + mască). Pentru o singură scanare se pot seta mai multe filtre — dispozitivul trebuie să corespundă tuturor (logică AND). Pentru logică OR, porniți mai multe scanări.

kotlin
// Crearea ScanFilter pentru diferite scenarii
class ScanFilterFactory {

    // 1. Filtrare după UUID serviciu (Heart Rate Monitor)
    fun byHeartRateService(): ScanFilter {
        return ScanFilter.Builder()
            .setServiceUuid(
                ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB")
            )
            .build()
    }

    // 2. Filtrare după nume dispozitiv („iBeacon*")
    fun byDeviceName(): ScanFilter {
        return ScanFilter.Builder()
            .setDeviceName("Sensor")
            .build()
    }

    // 3.   MAC- (dispozitive)
    fun byMacAddress(mac: String): ScanFilter {
        return ScanFilter.Builder()
            .setDeviceAddress(mac)
            .build()
    }

    // 4. Filtru combinat (UUID + )
    fun combinedFilter(): List<ScanFilter> {
        return listOf(
            ScanFilter.Builder()
                .setServiceUuid(
                    ParcelUuid.fromString("0000A001-0000-1000-8000-00805F9B34FB")
                )
                .setDeviceName("MyDevice")
                .build()
        )
    }

    // 5.   date producător
    fun byManufacturer(companyId: Int, data: ByteArray, mask: ByteArray): ScanFilter {
        return ScanFilter.Builder()
            .setManufacturerData(companyId, data, mask)
            .build()
    }
}

Clasa ScanFilterFactory arată toate tipurile de filtre. byHeartRateService filtrează dispozitivele cu serviciu puls 0x180D. byDeviceName găsește dispozitive care conțin „Sensor” în nume (Apple recomandă nume unice pentru filtrare). byMacAddress — căutarea exactă a unui dispozitiv specific. combinedFilter — filtru AND după UUID și nume. byManufacturer — filtru după datele producătorului (de exemplu, pentru iBeacon se folosește company ID Apple 0x004C).

ScanCallback: procesarea rezultatelor și erorilor de scanare

ScanCallback — clasa abstractă pentru primirea rezultatelor scanării BLE. Conține trei metode: onScanResult — rezultat unic (tip callback, ScanResult), onBatchScanResults — lot de rezultate pentru reportDelay > 0, onScanFailed — cod de eroare. Toate metodele sunt apelate pe threadul principal Android (main thread). Pentru procesare lungă în onScanResult, utilizați corutine sau HandlerThread.

ScanResult conține: BluetoothDevice device (dispozitiv), int rssi (nivel semnal în dBm), ScanRecord scanRecord (date publicitare), long timestampNanos (timpul detectării de la pornirea sistemului). ScanRecord oferă: getServiceData() — UUID + date personalizate, getManufacturerSpecificData() — date producător, getAdvertiseFlags() — flaguri BLE. Tipul callback (callbackType) indică: CALLBACK_TYPE_ALL_MATCHES — potrivire cu filtrul, CALLBACK_TYPE_FIRST_MATCH — prima detectare, CALLBACK_TYPE_MATCH_LOST — pierderea dispozitivului.

Coduri de eroare onScanFailed: SCAN_FAILED_ALREADY_STARTED (1) — scanarea este deja pornită, SCAN_FAILED_APPLICATION_REGISTRATION_FAILED (2) — înregistrarea aplicației în stiva Bluetooth a eșuat, SCAN_FAILED_INTERNAL_ERROR (3) — eroare internă a stivei, SCAN_FAILED_FEATURE_UNSUPPORTED (4) — scanarea BLE nu este suportată pe dispozitiv.

kotlin
// Rezultate complete ale scanării și gestionarea erorilor
class ScanResultHandler {

    private val results = mutableListOf<ScanResult>()

    val scanCallback = object : ScanCallback() {

        // 1. Rezultat unic
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            // callbackType: 1 = ALL_MATCHES, 2 = FIRST_MATCH, 4 = MATCH_LOST
            if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
                onDeviceLost(result)
                return
            }

            // Adăugați la listă (deduplicare după adresă)
            val existingIndex = results.indexOfFirst {
                it.device.address == result.device.address
            }
            if (existingIndex >= 0) {
                results[existingIndex] = result  // actualizați RSSI
            } else {
                results.add(result)
            }

            // Extrageți datele din pachetul publicitar
            val record = result.scanRecord
            val serviceData = record?.serviceData
            val manufacturerData = record?.manufacturerSpecificData

            print("Found: ${result.device.name ?: "N/A"}, RSSI: ${result.rssi}")
        }

        // 2. Rezultate în lot (reportDelay > 0)
        override fun onBatchScanResults(results: MutableList<ScanResult>?) {
            results?.let { batch ->
                print("Batch: ${batch.size} devices")
            }
        }

        // 3. Eroare de scanare
        override fun onScanFailed(errorCode: Int) {
            val error = when (errorCode) {
                ScanCallback.SCAN_FAILED_ALREADY_STARTED -> "Already scanning"
                ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED -> "Registration failed"
                ScanCallback.SCAN_FAILED_INTERNAL_ERROR -> "Internal error"
                ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED -> "BLE not supported"
                else -> "Unknown error: $errorCode"
            }
            print("Error: $error")
        }
    }

    private fun onDeviceLost(result: ScanResult) {
        results.removeAll { it.device.address == result.device.address }
        print("Device lost: ${result.device.address}")
    }
}

Clasa ScanResultHandler procesează toate tipurile de callback BluetoothLeScanner. onScanResult actualizează lista dispozitivelor cu deduplicare după adresa MAC — RSSI este actualizat pentru dispozitivele deja găsite. CALLBACK_TYPE_MATCH_LOST semnalează pierderea dispozitivului (ștergere din listă). onBatchScanResults procesează rezultatele în loturi pentru reportDelay > 0. onScanFailed mapează codurile de eroare în mesaje lizibile — esențial pentru depanarea scanării BLE.

PendingIntent: scanare BLE în fundal prin BroadcastReceiver

Scanarea PendingIntent — mecanismul BluetoothLeScanner pentru scanarea BLE care funcționează chiar și când aplicația este în fundal (cu restricțiile Android 8+). În loc de ScanCallback, se folosește PendingIntent care trimite un Broadcast către BroadcastReceiver-ul sistemului la detectarea unui dispozitiv BLE. Aceasta permite aplicației să primească notificări despre dispozitivele BLE fără a fi în memorie (sistemul creează procesul la primirea broadcast-ului).

Restricții ale scanării în fundal: Pe Android 8+ (API 26) serviciile în fundal sunt limitate — scanarea PendingIntent ocolește această restricție prin BroadcastReceiver, pe care sistemul îl poate porni la primirea unui eveniment BLE. Pe Android 10+ (API 29) scanarea BLE în fundal este suplimentar limitată de politicile de economisire a energiei ale producătorilor (Xiaomi, Huawei, Samsung blochează operațiile BLE în fundal). Pentru scenarii critice BLE, este necesară o notificare cu foreground service.

kotlin
// Scanare BLE în fundal prin PendingIntent
class BackgroundBLEScanner(private val context: Context) {

    private val scanner: BluetoothLeScanner? by lazy {
        val adapter = BluetoothAdapter.getDefaultAdapter()
        adapter?.bluetoothLeScanner
    }

    fun startBackgroundScan() {
        // Creați PendingIntent pentru BroadcastReceiver
        val intent = Intent(context, BLEBroadcastReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        // Setări scanare în fundal
        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
            .setMatchMode(ScanSettings.MATCH_MODE_STICKY)
            .build()

        // Porniți scanarea în fundal
        scanner?.startScan(
            null,  // filtre
            settings,
            pendingIntent
        )
    }

    fun stopBackgroundScan() {
        val intent = Intent(context, BLEBroadcastReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            context, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        scanner?.stopScan(pendingIntent)
    }
}

// BroadcastReceiver   BLE-
class BLEBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // Obțineți rezultatele scanării
        val results = BluetoothLeScanner.getPendingIntentScanResults(intent)
        results?.let { scanResults ->
            for (result in scanResults) {
                // Trimiteți notificare utilizatorului
                showNotification(context, result.device.name ?: " ")
            }
        }
    }

    private fun showNotification(context: Context, name: String) {
        val notification = Notification.Builder(context, "ble_channel")
            .setSmallIcon(android.R.drawable.ic_dialog_info)
            .setContentTitle("BLE devices")
            .setContentText("Found: $name")
            .setAutoCancel(true)
            .build()
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE)
                as NotificationManager
        manager.notify(System.currentTimeMillis().toInt(), notification)
    }
}

Clasa BackgroundBLEScanner pornește scanarea BLE în fundal prin PendingIntent. startBackgroundScan creează un PendingIntent care, la detectarea unui dispozitiv BLE, trimite un Broadcast către BLEBroadcastReceiver. BroadcastReceiver extrage ScanResult prin getPendingIntentScanResults() și poate afișa o notificare sau trimite date pe server. Această abordare funcționează chiar dacă aplicația a fost încheiată de sistem — Android pornește BroadcastReceiver la primirea broadcast-ului.

Exemplu scanner BLE în Kotlin cu BluetoothLeScanner

Exemplu complet de scanner BLE în Kotlin, care folosește BluetoothLeScanner cu ScanSettings, ScanFilter și ScanCallback pentru a găsi dispozitive Heart Rate Monitor. Scannerul arată o listă a dispozitivelor găsite cu RSSI și UUID-uri servicii, cu posibilitatea de conectare prin BluetoothGatt.

kotlin
// Scanner BLE complet cu corutine în Kotlin
class DeviceScanner(private val context: Context) {

    private val adapter: BluetoothAdapter? by lazy {
        val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
                as BluetoothManager
        manager.adapter
    }

    private val scanner: BluetoothLeScanner? by lazy {
        adapter?.bluetoothLeScanner
    }

    fun startScan(duration: Long = 10000): Flow<ScanResult> = callbackFlow {
        // Verificați starea Bluetooth
        if (adapter?.isEnabled != true) {
            close(IllegalStateException("Bluetooth disabled"))
            return@callbackFlow
        }

        // Configurarea scanării
        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .build()

        val filters = listOf(
            ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
                .build()
        )

        val callback = object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                trySend(result)
            }

            override fun onScanFailed(errorCode: Int) {
                close(BLEException("Scan failed: $errorCode"))
            }
        }

        // Porniți scanarea
        scanner?.startScan(filters, settings, callback)

        // Oprire automată după durată
        delay(duration)
        scanner?.stopScan(callback)
        close()
    }.flowOn(Dispatchers.IO)

    fun stop() {
        scanner?.stopScan(object : ScanCallback() {})
    }
}

class BLEException(message: String) : Exception(message)

Clasa DeviceScanner folosește Kotlin Flow (callbackFlow) pentru scanarea reactivă BLE. Scanarea este pornită cu setările LOW_LATENCY și filtrul după UUID Heart Rate Service. Rezultatele sunt emise prin onScanResult în Flow. Oprire automată după durata specificată (10 secunde implicit). FlowOn(Dispatchers.IO) mută operațiile BLE în threadul de fundal. Această abordare permite utilizarea scanării BLE în arhitectura MVVM prin viewModelScope.launch și collect.

Întrebări frecvente

Ce este BluetoothLeScanner în Android?

BluetoothLeScanner — clasa Android (API 21+) pentru scanare BLE. Se obține prin BluetoothAdapter.getBluetoothLeScanner(). Suportă trei moduri de scanare (LOW_POWER, BALANCED, LOW_LATENCY), filtrare după UUID, nume și adresă MAC, rezultate în loturi și PendingIntent pentru scanare în fundal. Înlocuiește metoda învechită BluetoothAdapter.startLeScan().

Cu ce diferă LOW_POWER de LOW_LATENCY?

SCAN_MODE_LOW_POWER — mod fundal cu întârziere de detectare 5–10 secunde, consum minim de energie. SCAN_MODE_LOW_LATENCY — mod activ cu întârziere de aproximativ 100 ms, consum maxim de energie. SCAN_MODE_BALANCED — compromis (~2 secunde întârziere). Pentru scanare UI utilizați LOW_LATENCY, pentru monitorizare în fundal — LOW_POWER cu PendingIntent.

De ce BluetoothLeScanner nu găsește dispozitive?

Cauze: Bluetooth dezactivat (verificați adapter.isEnabled), permisiuni neacordate (BLUETOOTH_SCAN pe API 31+, ACCESS_FINE_LOCATION pe API 23–30), scanner = null (adaptor indisponibil), dispozitiv în afara razei sau filtru incorect utilizat. Verificați și onScanFailed — codul de eroare va indica cauza: SCAN_FAILED_ALREADY_STARTED (1) sau SCAN_FAILED_APPLICATION_REGISTRATION_FAILED (2).

Cum să scanați BLE în fundal pe Android?

Utilizați versiunea PendingIntent a startScan() — transmiteți PendingIntent în loc de ScanCallback. La detectarea unui dispozitiv BLE, Android trimite un Broadcast către BroadcastReceiver, care poate fi pornit de sistem chiar dacă aplicația este în fundal. Pentru Android 8+, adăugați BroadcastReceiver în manifest. Pe Android 10+, luați în considerare restricțiile de economisire a energiei ale producătorilor.

Câte dispozitive BLE pot fi detectate într-o singură scanare?

BluetoothLeScanner nu are o limită pentru numărul de dispozitive detectabile — limitarea depinde de saturația BLE a mediului. Într-un birou pot fi 20–50 de dispozitive BLE active, într-un centru comercial — sute. Pentru filtrare, utilizați ScanFilter (după UUID, nume). Fără filtrare, procesați rezultatele asincron — onScanResult poate fi apelat de zeci de ori pe secundă.

Rezumat

  • BluetoothLeScanner — clasa modernă Android (API 21+) pentru scanare BLE cu setări și filtrare
  • ScanSettings — trei moduri: LOW_POWER (fundal), BALANCED (echilibrat), LOW_LATENCY (activ)
  • ScanFilter — filtrare după UUID serviciu, nume dispozitiv, adresă MAC, date producător cu logică AND
  • ScanCallback — onScanResult (individuale), onBatchScanResults (în loturi), onScanFailed (coduri de eroare)
  • PendingIntent — scanare în fundal prin BroadcastReceiver, funcționează cu aplicația încheiată
  • ScanRecord — date publicitare BLE: serviceData, manufacturerSpecificData, advertiseFlags, TX power level
  • Kotlin Flow — callbackFlow permite utilizarea BluetoothLeScanner în arhitectură reactivă cu oprire automată

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și