Библиотека Android Beacon: как сканировать iBeacon в фоновом режиме без использования внутреннего механизма JobSchedulerAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Библиотека Android Beacon: как сканировать iBeacon в фоновом режиме без использования внутреннего механизма JobScheduler

Сообщение Anonymous »

Около недели я пытался реализовать функцию сканирования чипов iBeacon в фоновом режиме с помощью WorkManager (периодически, каждые 15 минут).
Я реализовал сканирование чипов 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)
Вот код для сканирования чипа в фоновом режиме с помощью WorkManager:

Код: Выделить всё

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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»