使用IntentService附近的消息

Bry*_*yan 6 android android-intentservice android-ble beacon google-nearby

最初我设置了一个BroadcastReceiver接收来自Nearby Messages API的意图.

class BeaconMessageReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Nearby.getMessagesClient(context).handleIntent(intent, object : MessageListener() {
            override fun onFound(message: Message) {
                val id = IBeaconId.from(message)
                Timber.i("Found iBeacon=$id")
                sendNotification(context, "Found iBeacon=$id")
            }

            override fun onLost(message: Message) {
                val id = IBeaconId.from(message)
                Timber.i("Lost iBeacon=$id")
                sendNotification(context, "Lost iBeacon=$id")
            }
        })
    }

    private fun sendNotification(context: Context, text: String) {
        Timber.d("Send notification.")
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        val notification = NotificationCompat.Builder(context, Notifications.CHANNEL_GENERAL)
                .setContentTitle("Beacons")
                .setContentText(text)
                .setSmallIcon(R.drawable.ic_notification_white)
                .build()

        manager.notify(NotificationIdGenerator.nextID(), notification)
    }

}
Run Code Online (Sandbox Code Playgroud)

然后在我的MainActivity后位置权限中注册了此接收器已被授予.

class MainActivity : AppCompatActivity() {

    // ...

    private fun onLocationPermissionsGranted() {
        val filter = MessageFilter.Builder()
                .includeIBeaconIds(UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FEED"), null, null)
                .build()

        val options = SubscribeOptions.Builder().setStrategy(Strategy.BLE_ONLY).setFilter(filter).build()

        Nearby.getMessagesClient(context).subscribe(getPendingIntent(), options)
    }

    private fun getPendingIntent(): PendingIntent = PendingIntent.getBroadcast(
            this, 0, Intent(context, BeaconMessageReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)

}
Run Code Online (Sandbox Code Playgroud)

应用程序打开时,这很有效,但在应用程序关闭时无效.所以我找到了这个示例,它演示了如何IntentService在应用程序处于后台时设置接收消息.

该示例确实使用了Nearby.Messages该类,该类已被弃用以支持MessagesClient.所以我用MessagesClient实现替换了已弃用的代码.

class MainActivity : AppCompatActivity() {

    // ...

    private fun onLocationPermissionsGranted() {
        val filter = MessageFilter.Builder()
                .includeIBeaconIds(UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FEED"), null, null)
                .build()

        val options = SubscribeOptions.Builder().setStrategy(Strategy.BLE_ONLY).setFilter(filter).build()

        Nearby.getMessagesClient(context).subscribe(getPendingIntent(), options)
            .addOnSuccessListener {
                Timber.i("Subscribed successfully.")
                startService(Intent(this, BeaconMessageIntentService::class.java))
            }.addOnFailureListener {
                Timber.e(exception, "Subscription failed.")
            }
    }

    private fun getPendingIntent(): PendingIntent = PendingIntent.getBroadcast(
            this, 0, Intent(context, BeaconMessageIntentService::class.java), PendingIntent.FLAG_UPDATE_CURRENT)

}
Run Code Online (Sandbox Code Playgroud)

这就是IntentService(这几乎与我相同BroadcastReceiver).

class BeaconMessageIntentService : IntentService("BeaconMessageIntentService") {

    override fun onHandleIntent(intent: Intent?) {
        intent?.let {
            Nearby.getMessagesClient(this)
                    .handleIntent(it, object : MessageListener() {
                        override fun onFound(message: Message) {
                            val id = IBeaconId.from(message)
                            Timber.i("Found iBeacon=$id")
                            sendNotification("Found iBeacon=$id")
                        }

                        override fun onLost(message: Message) {
                            val id = IBeaconId.from(message)
                            Timber.i("Lost iBeacon=$id")
                            sendNotification("Lost iBeacon=$id")
                        }
                    })
        }
    }

    private fun sendNotification(text: String) {
        Timber.d("Send notification.")
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        val notification = NotificationCompat.Builder(this, Notifications.CHANNEL_GENERAL)
                .setContentTitle("Beacons")
                .setContentText(text)
                .setSmallIcon(R.drawable.ic_notification_white)
                .build()

        manager.notify(NotificationIdGenerator.nextID(), notification)
    }

}
Run Code Online (Sandbox Code Playgroud)

onHandleIntent被称为,而Intent不是null; 但由于某种原因onFound(),onLost()从未被称为.为什么会这样呢?

Mik*_*keL 2

这并不是一个真正的解决方案,但我发现的是这个(归功于这个答案):
我尝试了一些配置,包括 aBroadcastReceiver并添加 aJobIntentService在后台运行代码,但每次我得到这个onExpired回调时,你都可以设置至SubscribeOptions

options.setCallback(new SubscribeCallback() {
    @Override
    public void onExpired() {
        super.onExpired();
        Toast.makeText(context.get(), "No longer Subscribing!", Toast.LENGTH_SHORT).show();
    }
}
Run Code Online (Sandbox Code Playgroud)

当订阅在后台发生时,它会被延迟,但它仍然被调用。

注意:
1. 当我测试时,Strategy.BLE_ONLY我没有收到onFound回调。
2.来自谷歌的文档

后台订阅比前台订阅耗电更少,但延迟更高、可靠性更低

在测试时,我发现这种“较低的可靠性”是一种轻描淡写的说法:onFound很少被调用,而且我从未得到过onLost