Я реализовал сканирование чипов iBeacon, когда приложение открывается (на переднем плане) и при закрытии (в фоновом режиме с помощью WorkManager).
При открытии приложения (на переднем плане) чип сканируется быстро, примерно в пределах 100-1000 миллисекунды.
Но когда приложение закрыто, сканирование работает нестабильно. Иногда (редко) он может сканировать чип довольно быстро, за 500-1000 миллисекунд, но в большинстве случаев это занимает более 30-60 секунд (что довольно долго) или может вообще не обнаружить чип, хотя чип всегда включен.
Вот код Util, который я реализовал для сканирования:
Код: Выделить всё
object BeaconScanUtil {
private lateinit var applicationContext: Context
private val uuid = Identifier.parse("39ED98FF-2900-441A-802F-9C398FC199D2")
private var region = Region("all-beacons", uuid, null, null)
var currentBluetoothId: Int? = null
private val rangingObserver by lazy {
Observer { beacons ->
val beacon = beacons.firstOrNull()
if (beacon != null) {
val majorId = beacon.id2.toInt()
currentBluetoothId = majorId
stopScanning()
}
}
}
// I call this method from the Application.onCreate()
fun initialize(context: Context) {
applicationContext = context.applicationContext
BeaconManager.getInstanceForApplication(applicationContext).apply {
// Since we don't care about AltBeacon, we clear it from the defaults
beaconParsers.clear()
val parser = BeaconParser().apply {
// Layout for iBeacon
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")
setHardwareAssistManufacturerCodes(arrayOf(0x004c).toIntArray())
}
beaconParsers.add(parser)
setEnableScheduledScanJobs(false)
getRegionViewModel(region).rangedBeacons.observeForever(rangingObserver)
}
}
suspend fun scanForBeacons(maxDurationMs: Long, backgroundMode: Boolean): BeaconScanResult? {
val minDurationMs = 500L // 0.5s
val intervalMs = 100L // 0.1s
var durationMs = 0L
startScanning(backgroundMode)
try {
while (durationMs < maxDurationMs) {
if (durationMs >= minDurationMs) {
val currentBluetoothId = currentBluetoothId
if (currentBluetoothId != null) {
return BeaconScanResult(currentBluetoothId, durationMs)
}
}
durationMs += intervalMs
delay(intervalMs)
}
val currentBluetoothId = currentBluetoothId
return if (currentBluetoothId != null) {
BeaconScanResult(currentBluetoothId, durationMs)
} else {
null
}
} finally {
stopScanning()
}
}
private fun startScanning(backgroundMode: Boolean) {
resetBeaconsInfo()
val beaconManager = BeaconManager.getInstanceForApplication(applicationContext)
beaconManager.setBackgroundModeInternal(backgroundMode)
beaconManager.startRangingBeacons(region)
}
private fun stopScanning() {
val beaconManager = BeaconManager.getInstanceForApplication(applicationContext)
beaconManager.stopRangingBeacons(region)
}
private fun resetBeaconsInfo() {
currentBluetoothId = null
}
}
data class BeaconScanResult(val bluetoothId: Int, val timeSpentOnScanMs: Long)
Код: Выделить всё
class ScanBeaconWorker(
context: Context,
param: WorkerParameters
) : CoroutineWorker(context, param) {
override suspend fun doWork(): Result {
return withContext(Dispatchers.IO) {
val hasAllConditionsToScanForBeacon = ...
if (!hasAllConditionsToScanForBeacon) {
return@withContext Result.failure()
}
val timeToFindBeacon = BeaconScanUtil.scanForBeacons(
maxDurationMs = 60_000L,
backgroundMode = true
)
showAutoCheckInCheckInNotification(
context = applicationContext,
title = "Time: ${timeToFindBeacon?.timeSpentOnScanMs ?: 60_000}",
description = "Beacon ID: ${timeToFindBeacon?.bluetoothId}"
)
return@withContext Result.success()
}
}
private fun showAutoCheckInCheckInNotification(
context: Context,
title: String,
description: String,
) {
// show notification
}
}
- Не могли бы вы помочь мне понять, что может быть не так с этим кодом?
- Работает ли startRangingBeacons(region) в фоновом режиме? Или мне следует вместо этого использовать startMonitoring(region)? (Мне нужно значение основного маяка)
- Или не могли бы вы предоставить правильный пример кода для сканирования маяков без использования внутренний механизм JobScadular? (поскольку вместо этого я использую собственный WorkManager для выполнения сканирования в фоновом режиме)
- Или мне следует использовать другой подход для сканирования маяков в фоновом режиме ?
Большое спасибо заранее!
Я использую эту библиотеку:
https://altbeacon.github.io/android-bea ... index.html
Подробнее здесь: https://stackoverflow.com/questions/791 ... using-inne
Мобильная версия