最初,我设置了一个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)
}
}
然后在授予位置权限后将该接收者注册到我的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)
}
此功能在打开应用程序时很好用,但是在关闭应用程序时不起作用。因此,我发现了this example,它演示了如何设置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)
}
这是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)
}
}
onHandleIntent
被调用,而Intent
不是null
;但由于某些原因,从未调用onFound()
和onLost()
。为什么会这样?
答案 0 :(得分:2)
这不是真正的解决方案,但我发现的是这个(credit to this answer):
我尝试了一些配置,包括BroadcastReceiver
和添加JobIntentService
来在后台运行代码,但是每次我得到onExpired
回调时,都可以将其设置为{ {1}}:
SubscribeOptions
当订阅在后台发生时,它被延迟,但仍被调用。
注意:
1.用options.setCallback(new SubscribeCallback() {
@Override
public void onExpired() {
super.onExpired();
Toast.makeText(context.get(), "No longer Subscribing!", Toast.LENGTH_SHORT).show();
}
}
测试后,没有得到Strategy.BLE_ONLY
回调。
2.从Google的documentation:
后台订阅比前台消耗的电量更少 订阅,但具有较高的延迟和较低的可靠性
在测试时,我发现这种“ 低可靠性”被轻描淡写:onFound
很少被调用,而我却从未得到过onFound
。
答案 1 :(得分:0)
我知道这是一个较晚的答复,但是我遇到了同样的问题,并且通过调试发现这是与以下错误有关的问题:“试图从非活动上下文执行大功率操作”。在调用Nearby.getMessagesClient(this)
时,可以通过传入活动上下文而不是传递此上下文来解决此问题。
在我的情况下,我添加了一个扩展应用程序的类,该类有助于返回此上下文(以下内容位于Java中,但应可轻松转换为kotlin)
public class MyApplication extends Application {
private Activity currentActivity = null;
public Activity getCurrentActivity(){
return currentActivity;
}
public void setCurrentActivity(Activity mCurrentActivity){
this.currentActivity = mCurrentActivity;
}
}
在所有活动都从其扩展的基础活动中,我通过在构造函数中调用((MyApplication) this.getApplicationContext()).setCurrentActivity(this);
来设置当前活动。
然后我的服务可以使用如下所示的正确上下文调用getMessagesClient:
final Activity context = ((MyApplication)getApplicationContext()).getCurrentActivity();
Nearby.getMessagesClient(context).[...]
不要忘记在AndroidManifest中注册您的Application类:
<application
android:name="com.example.xxx.MyApplication"`