Android AltBeacon фон и передний план вместе - PullRequest
0 голосов
/ 22 ноября 2018

Добрый день.В моем приложении я хочу использовать фоновое и переднее сканирование маяков.Для этой задачи я использовал библиотеку AltBeacon.Но после перезагрузки устройства фоновое сканирование не запускается.

Мой алгоритм выглядит следующим образом:

  • Когда приложение запущено, запустите монитор и подключите прослушиватель жизненного цикла, чтобы определить, когда активность умирает.

  • Когда активность умирает - запустите фоновое сканирование.

  • Когда активность переходит на передний план - остановите задний план и запустите передний план.

Что у меня сейчас:

На первом - передний план "сервис" (на самом деле не сервис, просто класс)

class BeaconForegroundService(private val application: Application) : BeaconConsumer {

private var beaconManager: BeaconManager? = null

companion object {
    private const val REGION_UID = "region_uid"
}

override fun getApplicationContext(): Context {
    return application.applicationContext
}

override fun unbindService(p0: ServiceConnection) {
    application.unbindService(p0)
}

override fun bindService(p0: Intent, p1: ServiceConnection, p2: Int): Boolean {
    return application.bindService(p0, p1, p2)
}

override fun onBeaconServiceConnect() {

    beaconManager!!.beaconParsers.clear()
    beaconManager!!.beaconParsers.add(AltBeaconParser())
    beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.URI_BEACON_LAYOUT))
    beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT))
    beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
    beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT))
    beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"))
    beaconManager!!.backgroundMode = false

    beaconManager!!.addMonitorNotifier(object : MonitorNotifier {
        override fun didDetermineStateForRegion(p0: Int, p1: Region?) {
            Timber.d("FGBeacon: didDetermineStateForRegion INSIDE = ${p0 == MonitorNotifier.INSIDE}")
        }

        override fun didEnterRegion(p0: Region?) {
            Timber.d("FGBeacon: didEnterRegion")
        }

        override fun didExitRegion(p0: Region?) {
            Timber.d("FGBeacon: didExitRegion")
        }
    })
    beaconManager!!.addRangeNotifier { mutableCollection: MutableCollection<Beacon>, region: Region ->
        Timber.d("FGBeacon $mutableCollection")
    }
    beaconManager!!.startMonitoringBeaconsInRegion(Region(REGION_UID, null, null, null))
    beaconManager!!.startRangingBeaconsInRegion(Region(REGION_UID, null, null, null))
}

fun startScan() {
    beaconManager = BeaconManager.getInstanceForApplication(application)
    beaconManager!!.bind(this)
}

fun stopScan() {
    beaconManager?.unbind(this)
}

}

Фоновое сканирование внутрикласс приложения:

class MyApplication : Application(), BootstrapNotifier {

// Fields
private var beaconManager: BeaconManager? = null
private var backgroundPowerSaver: BackgroundPowerSaver ?= null
private var regionBootstrap : RegionBootstrap ?= null
private var foregroundService: BeaconForegroundService ?= null
val REGION_UID = "region_uid"

//Method for start background scan here

fun startScan() {
        beaconManager = BeaconManager.getInstanceForApplication(this)
        beaconManager!!.beaconParsers.clear()
        beaconManager!!.beaconParsers.add(AltBeaconParser())
        beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.URI_BEACON_LAYOUT))
        beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_TLM_LAYOUT))
        beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_UID_LAYOUT))
        beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT))
        beaconManager!!.beaconParsers.add(BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"))

        val notificationBuilder = Notification.Builder(this)
        notificationBuilder.setSmallIcon(R.drawable.ic_launcher_foreground)
        notificationBuilder.setContentTitle("Scanning for beacons")
        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(this, MainActivity.BEACON_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        notificationBuilder.setContentIntent(pendingIntent)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel("MyChannelId", "NotyName", NotificationManager.IMPORTANCE_DEFAULT)
            channel.description = "NotyDesc"
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
            notificationBuilder.setChannelId(channel.id)
        }




        val region = Region(REGION_UID, null, null, null)

        beaconManager!!.enableForegroundServiceScanning(notificationBuilder.build(), 456)
        beaconManager!!.setEnableScheduledScanJobs(false)
        beaconManager!!.backgroundBetweenScanPeriod = 0
        beaconManager!!.backgroundScanPeriod = TimeUnit.SECONDS.toMillis(5)
        beaconManager!!.backgroundMode = true

        regionBootstrap  = RegionBootstrap(this, region)
        backgroundPowerSaver = BackgroundPowerSaver(this)

        beaconManager!!.addRangeNotifier { mutableCollection: MutableCollection<Beacon>, r: Region ->
            Timber.d("PBeacon $mutableCollection")
        }
    }

//Disable background scan if application start in foreground
fun disableMonitoring() {
        regionBootstrap?.disable()
        regionBootstrap = null
        beaconManager?.removeAllRangeNotifiers()
    }

  override fun didDetermineStateForRegion(p0: Int, p1: Region?) {
        Timber.d("PBeacon: StateForRegion INSIDE = ${p0 == MonitorNotifier.INSIDE}")
    }

//Start ranging if we inside region
    override fun didEnterRegion(p0: Region?) {
        Timber.d("PBeacon: I see a beacon first time")
        beaconManager!!.startRangingBeaconsInRegion(Region(REGION_UID, null, null, null))

    }

//Stop ranging if we move out from region
    override fun didExitRegion(p0: Region?) {
        Timber.d("PBeacon : I no longer see a beacon.")
        beaconManager!!.stopRangingBeaconsInRegion(Region(REGION_UID, null, null, null))
    }

И, наконец, зарегистрированный прослушиватель для обнаружения изменений состояния приложения переднего плана / фона (внутри onCreate приложения)

registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {

            //Stop background scan and start foreground
            override fun onActivityStarted(activity: Activity?) {
                disableMonitoring() 

                foregroundService = BeaconForegroundService(this@MyApplication)
                foregroundService!!.startScan()
            }

              //Stop foreground scan and start background
              override fun onActivityStopped(activity: Activity?) {
                foregroundService?.stopScan()
                foregroundService = null

                startScan()
            }

        })

Журналы здесь:

Журналы при запуске приложения на переднем плане (выглядит нормально)

D/BeaconParser: Parsing beacon layout: m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25
D/BeaconParser: Parsing beacon layout: m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25
D/BeaconParser: Parsing beacon layout: s:0-1=fed8,m:2-2=00,p:3-3:-41,i:4-21v
D/BeaconParser: Parsing beacon layout: x,s:0-1=feaa,m:2-2=20,d:3-3,d:4-5,d:6-7,d:8-11,d:12-15
D/BeaconParser: Parsing beacon layout: s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19
D/BeaconParser: Parsing beacon layout: s:0-1=feaa,m:2-2=10,p:3-3:-41,i:4-21v
D/BeaconParser: Parsing beacon layout: m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25
....
BeaconForegroundService$onBeaconServiceConnect: [id1: b5b182c7-eab1-4988-aa99-b5c1517008d9 id2: 1 id3: 57197]

Закрыть приложение (фоновый режим?):

Processing pdu type FF: 0201061aff4c000215b5b182c7eab14988aa99b5c1517008d90001df6dc50d0961626561636f6e5f36444446000000000000000000000000000000000000 with startIndex: 5, endIndex: 29
D/BeaconParser: This is not a matching Beacon advertisement. Was expecting aa fe at offset 5 and 20 at offset 7.  The bytes I see are: 0201061aff4c000215b5b182c7eab14988aa99b5c1517008d90001df6dc50d0961626561636f6e5f36444446000000000000000000000000000000000000
 D/BeaconParser: Ignoring pdu type 01
...
 D/BeaconParser: Processing pdu type FF: 0201061aff4c000215b5b182c7eab14988aa99b5c1517008d90001df6dc50d0961626561636f6e5f36444446000000000000000000000000000000000000 with startIndex: 5, endIndex: 29
D/BeaconParser: This is a recognized beacon advertisement -- 02 15 seen
D/BeaconParser: Bytes are: 0201061aff4c000215b5b182c7eab14988aa99b5c1517008d90001df6dc50d0961626561636f6e5f36444446000000000000000000000000000000000000
D/ScanHelper: Beacon packet detected for: id1: b5b182c7-eab1-4988-aa99-b5c1517008d9 id2: 1 id3: 57197 with rssi -46
D/RangeState: adding id1: b5b182c7-eab1-4988-aa99-b5c1517008d9 id2: 1 id3: 57197 to existing range for: org.altbeacon.beacon.service.RangedBeacon@332c859

После перезагрузки:

I/BeaconManager: BeaconManager started up on pid 7407 named 'com.myapp' for application package 'com.myapp'.  isMainProcess=true
D/BeaconParser: Parsing beacon layout: m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25

И это все.Нет обнаружений, ожидание (20+ минут)

Итак

  1. Это ошибка библиотеки / устройства или я что-то не так делаю?
  2. Можно ли использовать фоновое сканирование безУведомление?
  3. Когда мы запускаем приложение снова (на передний план), уведомление обновляется.Как я могу избежать этого?

Большое спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...