BluetoothLeScanner — η κλάση Android για σάρωση συσκευών Bluetooth Low Energy, διαθέσιμη από API 21 (Android 5.0). Το BluetoothLeScanner αντικατέστησε την παρωχημένη μέθοδο startLeScan στο BluetoothAdapter, παρέχοντας ευέλικτο API με ρύθμιση σάρωσης (ScanSettings), φιλτράρισμα (ScanFilter) και υποστήριξη λειτουργίας υποβάθρου (PendingIntent). Το στέλεχος λαμβάνεται μέσω BluetoothAdapter.getBluetoothLeScanner(). Σύμφωνα με Android Developers, 2026, το BluetoothLeScanner υποστηρίζει τρεις λειτουργίες κατανάλωσης ενέργειας και επιτρέπει τη σάρωση διαφημιστικών πακέτων BLE με φιλτράρισμα βάσει UUID υπηρεσίας, ονόματος συσκευής ή MAC διεύθυνσης.
Βασικά σημεία
BluetoothLeScanner — η κλάση συστήματος για διαχείριση σάρωσης BLE στο Android. Σε αντίθεση με το BluetoothAdapter.startLeScan() που δέχεται ένα απλό callback LeScanCallback, το BluetoothLeScanner παρέχει αντικειμενοστραφές API με ρυθμίσεις, φίλτρα και εκτεταμένη διαχείριση σφαλμάτων. Η κλάση εμφανίστηκε στο API 21 (Android 5.0) μαζί με υποστήριξη BLE 4.2 και παραμένει η κύρια μέθοδος σάρωσης BLE σε όλες τις σύγχρονες εκδόσεις Android.
Η λήψη στελέχους BluetoothLeScanner γίνεται μέσω BluetoothAdapter.getBluetoothLeScanner(). Η μέθοδος επιστρέφει null εάν ο προσαρμογέας Bluetooth δεν είναι διαθέσιμος (Bluetooth απενεργοποιημένο ή η συσκευή δεν υποστηρίζει BLE). Πριν από τη λήψη, ελέγξτε το BluetoothAdapter.isEnabled() και την παρουσία FEATURE_BLUETOOTH_LE μέσω PackageManager. Μετά τη λήψη του σαρωτή, μπορείτε να ξεκινήσετε σάρωση σε οποιοδήποτε νήμα — το Android προγραμματίζει μόνο του τις λειτουργίες BLE στο εσωτερικό νήμα της στοίβας Bluetooth.
// Λήψη 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 {
// Ελέγξτε διαθεσιμότητα BLE
if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
return false
}
// Ελέγξτε Bluetooth ενεργοποιημένο
if (adapter?.isEnabled != true) {
return false
}
// Λήψη σαρωτή
scanner = adapter?.bluetoothLeScanner
return scanner != null
}
// Ελέγξτε διαθεσιμότητα σαρωτή
val isAvailable: Boolean
get() = scanner != null
// Έναρξη βασικής σάρωσης χωρίς φίλτρα
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}")
}
}
Η κλάση BLEScannerManager δείχνει την ασφαλή λήψη και αρχικοποίηση του BluetoothLeScanner. Το initScanner ελέγχει την παρουσία BLE μέσω hasSystemFeature, το ενεργοποιημένο Bluetooth και την επιτυχή λήψη του σαρωτή. Το startBasicScan ξεκινά σάρωση χωρίς ρυθμίσεις και φίλτρα — ανιχνεύει όλες τις συσκευές BLE στην εμβέλεια. Το handleResult αναλύει το ScanResult: BluetoothDevice (όνομα, διεύθυνση), RSSI (επίπεδο σήματος), scanRecord (διαφημιστικά δεδομένα).
ScanSettings — κλάση για διαμόρφωση σάρωσης BLE. Η κύρια παράμετρος είναι η λειτουργία σάρωσης (scanMode), που καθορίζει τη συμβιβαστική λύση μεταξύ κατανάλωσης ενέργειας και καθυστέρησης ανίχνευσης. Το ScanSettings.Builder επιτρέπει τη διαμόρφωση: scanMode, callbackType (CALLBACK_TYPE_ALL_MATCHES, CALLBACK_TYPE_FIRST_MATCH, CALLBACK_TYPE_MATCH_LOST), matchMode (MATCH_MODE_AGGRESSIVE, MATCH_MODE_STICKY), reportDelay (καθυστέρηση μαζικής αποστολής) και phy (PHY_LE_1M, PHY_LE_2M, PHY_LE_CODED).
Τρεις λειτουργίες σάρωσης: SCAN_MODE_LOW_POWER (0) — σάρωση υποβάθρου με χαμηλή κατανάλωση ενέργειας, καθυστέρηση ανίχνευσης αρκετά δευτερόλεπτα. SCAN_MODE_BALANCED (1) — ισορροπημένη λειτουργία για τα περισσότερα σενάρια. SCAN_MODE_LOW_LATENCY (2) — ελάχιστη καθυστέρηση ανίχνευσης (περίπου 100 ms), μέγιστη κατανάλωση ενέργειας. Για ενεργή αναζήτηση συσκευών χρησιμοποιήστε LOW_LATENCY, για παρακολούθηση υποβάθρου — LOW_POWER.
reportDelay — καθυστέρηση σε χιλιοστά του δευτερολέπτου πριν από τη μαζική αποστολή αποτελεσμάτων. Εάν reportDelay = 0, τα αποτελέσματα αποστέλλονται αμέσως μετά την ανίχνευση. Εάν > 0, το Android συσσωρεύει τα αποτελέσματα και στέλνει παρτίδα μέσω onBatchScanResults. Η μαζική αποστολή μειώνει τον αριθμό κλήσεων callback και μειώνει την κατανάλωση ενέργειας, κατάλληλη για σάρωση υποβάθρου χαμηλής προτεραιότητας.
// Διαμόρφωση ScanSettings για διαφορετικά σενάρια
class ScanSettingsProvider {
// 1. Γρήγορη σάρωση (ενεργή αναζήτηση)
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. Ενεργειακά αποδοτική σάρωση (παρακολούθηση υποβάθρου)
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) // παρτίδα κάθε 2 δευτερόλεπτα
.build()
}
// 3. Σάρωση 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. Σάρωση μόνο σε 2M PHY (BLE 5.0+)
fun highSpeedScan(): ScanSettings {
return ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setPhy(ScanSettings.PHY_LE_2M)
.build()
}
}
Η κλάση ScanSettingsProvider περιέχει τυπικές διαμορφώσεις. lowLatencyScan — για σάρωση UI (αναζήτηση "εδώ και τώρα"). lowPowerScan — για παρακολούθηση υποβάθρου με παρτίδα κάθε 2 δευτερόλεπτα και callbackType FIRST_MATCH (ενεργοποιείται μόνο στην πρώτη ανίχνευση). longRangeScan χρησιμοποιεί PHY_LE_CODED (BLE Long Range, έως 1 km). highSpeedScan — PHY_LE_2M (2 Mbit/s, μόνο συσκευές BLE 5.0+).
ScanFilter — κλάση για φιλτράρισμα αποτελεσμάτων σάρωσης BLE. Χωρίς φίλτρο, το BluetoothLeScanner επιστρέφει όλες τις συσκευές BLE στην εμβέλεια — σε πυκνό περιβάλλον BLE, αυτό σημαίνει εκατοντάδες πακέτα ανά λεπτό. Το ScanFilter περιορίζει τα αποτελέσματα στις απαραίτητες συσκευές, μειώνοντας την κατανάλωση ενέργειας και το φορτίο της εφαρμογής. Τα φίλτρα εφαρμόζονται σε επίπεδο στοίβας Bluetooth — τα ακατάλληλα πακέτα απορρίπτονται πριν από την παράδοση στην εφαρμογή.
Τύποι φίλτρων: setServiceUuid — UUID υπηρεσίας (υποχρεωτικά πλήρης μορφή 128-bit). setDeviceName — υποσυμβολοσειρά ονόματος συσκευής (διάκριση πεζών-κεφαλαίων, ακριβής αντιστοίχιση υποσυμβολοσειράς). setDeviceAddress — ακριβής MAC διεύθυνση. setManufacturerData — δεδομένα κατασκευαστή (ID εταιρείας + μάσκα). Για μία σάρωση μπορούν να οριστούν πολλά φίλτρα — η συσκευή πρέπει να ταιριάζει με όλα (AND λογική). Για OR λογική, εκτελέστε πολλές σαρώσεις.
// Δημιουργία ScanFilter για διαφορετικά σενάρια
class ScanFilterFactory {
// 1. Φιλτράρισμα βάσει UUID υπηρεσίας (Heart Rate Monitor)
fun byHeartRateService(): ScanFilter {
return ScanFilter.Builder()
.setServiceUuid(
ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB")
)
.build()
}
// 2. Φιλτράρισμα βάσει ονόματος συσκευής ("iBeacon*")
fun byDeviceName(): ScanFilter {
return ScanFilter.Builder()
.setDeviceName("Sensor")
.build()
}
// 3. MAC- (συσκευές)
fun byMacAddress(mac: String): ScanFilter {
return ScanFilter.Builder()
.setDeviceAddress(mac)
.build()
}
// 4. Συνδυασμένο φίλτρο (UUID + )
fun combinedFilter(): List<ScanFilter> {
return listOf(
ScanFilter.Builder()
.setServiceUuid(
ParcelUuid.fromString("0000A001-0000-1000-8000-00805F9B34FB")
)
.setDeviceName("MyDevice")
.build()
)
}
// 5. δεδομένα κατασκευαστή
fun byManufacturer(companyId: Int, data: ByteArray, mask: ByteArray): ScanFilter {
return ScanFilter.Builder()
.setManufacturerData(companyId, data, mask)
.build()
}
}
Η κλάση ScanFilterFactory δείχνει όλους τους τύπους φίλτρων. byHeartRateService φιλτράρει συσκευές με υπηρεσία παλμού 0x180D. byDeviceName βρίσκει συσκευές που περιέχουν "Sensor" στο όνομα (η Apple συνιστά μοναδικά ονόματα για φιλτράρισμα). byMacAddress — ακριβής αναζήτηση συγκεκριμένης συσκευής. combinedFilter — AND φίλτρο βάσει UUID και ονόματος. byManufacturer — φίλτρο βάσει δεδομένων κατασκευαστή (π.χ. για iBeacon χρησιμοποιείται company ID Apple 0x004C).
ScanCallback — αφηρημένη κλάση για λήψη αποτελεσμάτων σάρωσης BLE. Περιέχει τρεις μεθόδους: onScanResult — μεμονωμένο αποτέλεσμα (τύπος callback, ScanResult), onBatchScanResults — παρτίδα αποτελεσμάτων για reportDelay > 0, onScanFailed — κωδικός σφάλματος. Όλες οι μέθοδοι καλούνται στο κύριο νήμα Android (main thread). Για μακροχρόνια επεξεργασία στο onScanResult, χρησιμοποιήστε coroutines ή HandlerThread.
ScanResult περιέχει: BluetoothDevice device (συσκευή), int rssi (επίπεδο σήματος σε dBm), ScanRecord scanRecord (διαφημιστικά δεδομένα), long timestampNanos (χρόνος ανίχνευσης από την εκκίνηση συστήματος). Το ScanRecord παρέχει: getServiceData() — UUID + προσαρμοσμένα δεδομένα, getManufacturerSpecificData() — δεδομένα κατασκευαστή, getAdvertiseFlags() — σημαίες BLE. Ο τύπος callback (callbackType) υποδεικνύει: CALLBACK_TYPE_ALL_MATCHES — αντιστοίχιση με φίλτρο, CALLBACK_TYPE_FIRST_MATCH — πρώτη ανίχνευση, CALLBACK_TYPE_MATCH_LOST — απώλεια συσκευής.
Κωδικοί σφάλματος onScanFailed: SCAN_FAILED_ALREADY_STARTED (1) — η σάρωση έχει ήδη ξεκινήσει, SCAN_FAILED_APPLICATION_REGISTRATION_FAILED (2) — η εγγραφή της εφαρμογής στη στοίβα Bluetooth απέτυχε, SCAN_FAILED_INTERNAL_ERROR (3) — εσωτερικό σφάλμα στοίβας, SCAN_FAILED_FEATURE_UNSUPPORTED (4) — η σάρωση BLE δεν υποστηρίζεται στη συσκευή.
// Πλήρη αποτελέσματα σάρωσης και διαχείριση σφαλμάτων
class ScanResultHandler {
private val results = mutableListOf<ScanResult>()
val scanCallback = object : ScanCallback() {
// 1. Μεμονωμένο αποτέλεσμα
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
}
// Προσθήκη στη λίστα (αφαίρεση διπλότυπων βάσει διεύθυνσης)
val existingIndex = results.indexOfFirst {
it.device.address == result.device.address
}
if (existingIndex >= 0) {
results[existingIndex] = result // ενημέρωση RSSI
} else {
results.add(result)
}
// Εξαγωγή δεδομένων από διαφημιστικό πακέτο
val record = result.scanRecord
val serviceData = record?.serviceData
val manufacturerData = record?.manufacturerSpecificData
print("Found: ${result.device.name ?: "N/A"}, RSSI: ${result.rssi}")
}
// 2. Αποτελέσματα παρτίδας (reportDelay > 0)
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
results?.let { batch ->
print("Batch: ${batch.size} devices")
}
}
// 3. Σφάλμα σάρωσης
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}")
}
}
Η κλάση ScanResultHandler επεξεργάζεται όλους τους τύπους callback του BluetoothLeScanner. Το onScanResult ενημερώνει τη λίστα συσκευών με αφαίρεση διπλότυπων βάσει MAC διεύθυνσης — το RSSI ενημερώνεται για ήδη ευρεθείσες συσκευές. Το CALLBACK_TYPE_MATCH_LOST σηματοδοτεί απώλεια συσκευής (αφαίρεση από λίστα). Το onBatchScanResults επεξεργάζεται αποτελέσματα παρτίδας για reportDelay > 0. Το onScanFailed αντιστοιχίζει κωδικούς σφάλματος σε αναγνώσιμα μηνύματα — κρίσιμο για αποσφαλμάτωση σάρωσης BLE.
Σάρωση PendingIntent — μηχανισμός BluetoothLeScanner για σάρωση BLE που λειτουργεί ακόμη και όταν η εφαρμογή είναι στο παρασκήνιο (με περιορισμούς Android 8+). Αντί για ScanCallback, χρησιμοποιείται PendingIntent που στέλνει Broadcast στον BroadcastReceiver συστήματος κατά την ανίχνευση συσκευής BLE. Αυτό επιτρέπει στην εφαρμογή να λαμβάνει ειδοποιήσεις για συσκευές BLE χωρίς να βρίσκεται στη μνήμη (το σύστημα δημιουργεί διεργασία κατά τη λήψη broadcast).
Περιορισμοί σάρωσης υποβάθρου: Σε Android 8+ (API 26) οι υπηρεσίες υποβάθρου είναι περιορισμένες — η σάρωση PendingIntent παρακάμπτει αυτόν τον περιορισμό μέσω BroadcastReceiver, τον οποίο το σύστημα μπορεί να εκκινήσει κατά τη λήψη συμβάντος BLE. Σε Android 10+ (API 29) η σάρωση BLE υποβάθρου περιορίζεται περαιτέρω από πολιτικές εξοικονόμησης ενέργειας κατασκευαστών (Xiaomi, Huawei, Samsung μπλοκάρουν λειτουργίες BLE υποβάθρου). Για κρίσιμα σενάρια BLE, απαιτείται ειδοποίηση με foreground service.
// Σάρωση BLE υποβάθρου μέσω PendingIntent
class BackgroundBLEScanner(private val context: Context) {
private val scanner: BluetoothLeScanner? by lazy {
val adapter = BluetoothAdapter.getDefaultAdapter()
adapter?.bluetoothLeScanner
}
fun startBackgroundScan() {
// Δημιουργία PendingIntent για BroadcastReceiver
val intent = Intent(context, BLEBroadcastReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
// Ρυθμίσεις σάρωσης υποβάθρου
val settings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.setCallbackType(ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
.setMatchMode(ScanSettings.MATCH_MODE_STICKY)
.build()
// Έναρξη σάρωσης υποβάθρου
scanner?.startScan(
null, // φίλτρα
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) {
// Λήψη αποτελεσμάτων σάρωσης
val results = BluetoothLeScanner.getPendingIntentScanResults(intent)
results?.let { scanResults ->
for (result in scanResults) {
// Αποστολή ειδοποίησης στον χρήστη
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)
}
}
Η κλάση BackgroundBLEScanner ξεκινά σάρωση BLE υποβάθρου μέσω PendingIntent. Το startBackgroundScan δημιουργεί ένα PendingIntent που κατά την ανίχνευση συσκευής BLE στέλνει Broadcast στο BLEBroadcastReceiver. Το BroadcastReceiver εξάγει ScanResult μέσω getPendingIntentScanResults() και μπορεί να εμφανίσει ειδοποίηση ή να στείλει δεδομένα στον διακομιστή. Αυτή η προσέγγιση λειτουργεί ακόμη και αν η εφαρμογή τερματίστηκε από το σύστημα — το Android εκκινεί το BroadcastReceiver κατά τη λήψη broadcast.
Πλήρες παράδειγμα σαρωτή BLE σε Kotlin, που χρησιμοποιεί BluetoothLeScanner με ScanSettings, ScanFilter και ScanCallback για εύρεση συσκευών Heart Rate Monitor. Ο σαρωτής εμφανίζει λίστα ευρεθέντων συσκευών με RSSI και UUID υπηρεσιών, με δυνατότητα σύνδεσης μέσω BluetoothGatt.
// Πλήρης σαρωτής BLE με coroutines σε 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 {
// Ελέγξτε κατάσταση Bluetooth
if (adapter?.isEnabled != true) {
close(IllegalStateException("Bluetooth disabled"))
return@callbackFlow
}
// Διαμόρφωση σάρωσης
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"))
}
}
// Έναρξη σάρωσης
scanner?.startScan(filters, settings, callback)
// Αυτόματη διακοπή μετά από διάρκεια
delay(duration)
scanner?.stopScan(callback)
close()
}.flowOn(Dispatchers.IO)
fun stop() {
scanner?.stopScan(object : ScanCallback() {})
}
}
class BLEException(message: String) : Exception(message)
Η κλάση DeviceScanner χρησιμοποιεί Kotlin Flow (callbackFlow) για αντιδραστική σάρωση BLE. Η σάρωση ξεκινά με ρυθμίσεις LOW_LATENCY και φίλτρο βάσει UUID Heart Rate Service. Τα αποτελέσματα εκπέμπονται μέσω onScanResult στο Flow. Αυτόματη διακοπή μετά από καθορισμένη διάρκεια (10 δευτερόλεπτα προεπιλογή). Το FlowOn(Dispatchers.IO) μεταφέρει λειτουργίες BLE σε νήμα υποβάθρου. Αυτή η προσέγγιση επιτρέπει τη χρήση σάρωσης BLE σε αρχιτεκτονική MVVM μέσω viewModelScope.launch και collect.
Συχνές Ερωτήσεις
BluetoothLeScanner — κλάση Android (API 21+) για σάρωση BLE. Λαμβάνεται μέσω BluetoothAdapter.getBluetoothLeScanner(). Υποστηρίζει τρεις λειτουργίες σάρωσης (LOW_POWER, BALANCED, LOW_LATENCY), φιλτράρισμα βάσει UUID, ονόματος και MAC διεύθυνσης, αποτελέσματα παρτίδας και PendingIntent για σάρωση υποβάθρου. Αντικαθιστά την παρωχημένη μέθοδο BluetoothAdapter.startLeScan().
SCAN_MODE_LOW_POWER — λειτουργία υποβάθρου με καθυστέρηση ανίχνευσης 5–10 δευτερόλεπτα, ελάχιστη κατανάλωση ενέργειας. SCAN_MODE_LOW_LATENCY — ενεργή λειτουργία με καθυστέρηση περίπου 100 ms, μέγιστη κατανάλωση ενέργειας. SCAN_MODE_BALANCED — συμβιβασμός (~2 δευτερόλεπτα καθυστέρηση). Για σάρωση UI χρησιμοποιήστε LOW_LATENCY, για παρακολούθηση υποβάθρου — LOW_POWER με PendingIntent.
Αιτίες: Bluetooth απενεργοποιημένο (ελέγξτε adapter.isEnabled), δεν έχουν χορηγηθεί δικαιώματα (BLUETOOTH_SCAN σε API 31+, ACCESS_FINE_LOCATION σε API 23–30), scanner = null (προσαρμογέας μη διαθέσιμος), συσκευή εκτός εμβέλειας ή χρήση λανθασμένου φίλτρου. Ελέγξτε επίσης το onScanFailed — ο κωδικός σφάλματος θα υποδείξει την αιτία: SCAN_FAILED_ALREADY_STARTED (1) ή SCAN_FAILED_APPLICATION_REGISTRATION_FAILED (2).
Χρησιμοποιήστε την έκδοση PendingIntent του startScan() — μεταδώστε PendingIntent αντί για ScanCallback. Κατά την ανίχνευση συσκευής BLE, το Android στέλνει Broadcast στο BroadcastReceiver, το οποίο μπορεί να εκκινηθεί από το σύστημα ακόμη και αν η εφαρμογή είναι στο παρασκήνιο. Για Android 8+, προσθέστε το BroadcastReceiver στο manifest. Σε Android 10+, λάβετε υπόψη τους περιορισμούς εξοικονόμησης ενέργειας κατασκευαστών.
Το BluetoothLeScanner δεν έχει όριο στον αριθμό ανιχνεύσιμων συσκευών — ο περιορισμός εξαρτάται από τον κορεσμό BLE του περιβάλλοντος. Σε ένα γραφείο μπορεί να υπάρχουν 20–50 ενεργές συσκευές BLE, σε ένα εμπορικό κέντρο εκατοντάδες. Για φιλτράρισμα, χρησιμοποιήστε ScanFilter (βάσει UUID, ονόματος). Χωρίς φιλτράρισμα, επεξεργαστείτε τα αποτελέσματα ασύγχρονα — το onScanResult μπορεί να κληθεί δεκάδες φορές ανά δευτερόλεπτο.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης