美好的一天 . 在我的应用程序中,我想使用背景和前景信标扫描 . 对于此任务,我使用了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 of application中)

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()
            }

        })

Logs here:

应用程序在前台启动时记录(看起来很好)

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分钟)

所以

  • 是库/设备的错误还是我做错了什么?

  • 我们可以使用后台扫描而不通知吗?

  • 我们再次启动应用程序(到前台)刷新通知 . 我怎能避免这种情况?

十分感谢