隐式BroadcastReceiver的替代方案?

时间:2018-06-24 13:54:26

标签: android polling android-broadcast

我目前正在研究一种体系结构,以在应用程序之间传递交通消息(“在Como-Monte Olimpino和Brogeda之间的A9上的固定交通”)。

这些消息的来源是专用的应用程序:一个是通过TMC来提取消息的,另一个可能是从Internet上的各种服务中提取消息的。

在典型的用例中,消费者是导航应用程序,尽管其他用例也是可能的。

可以同时激活多个来源和使用者。

当源接收到新消息时,它将发送广播Intent,并将消息作为额外消息。消费者注册BroadcastReceiver来接收这些消息。 (邮件的有效载荷通常为几百个字节。)

当使用者启动时,我需要提供一种方法来轮询每个源以查找源可能在其缓存中的消息(同时请记住,该使用者无法知道哪些源可用)。

我最初的想法也是通过广播来做到这一点:在启动时,消费者将发送一个隐式广播,并且每个源都将以其当前活动消息的广播提要作为响应。

在使用者启动时,某些源可能没有运行,但是可能仍在其缓存中保留有需要传递给使用者的消息。如果应用未运行,由于上下文注册的BroadcastReceiver将无法捕获轮询广播,因此在清单中声明te接收器似乎是合乎逻辑的。

但是,从Android 8.0开始,manifest-declared receivers can no longer be used to receive implicit broadcasts。此外,this comment建议即使在较早版本和某些Android版本上,通过隐式广播唤醒应用程序也无法按预期进行(并且我正在开发设备的设备也具有该限制)

什么是让使用者从所有来源检索所有当前活动的消息(即使它们未运行)的良好机制?实施内容提供程序看起来有点过大,那么还有哪些其他选择可用?

1 个答案:

答案 0 :(得分:2)

您的消费者应用将需要知道:

  • 安装了哪些源

  • 用户希望消费者应用使用哪些来源的子集(因为用户可能不希望所有这些来源)

了解安装哪些源的可能方法包括:

  • 遍历已知的可能的源应用程序ID的列表,并使用PackageManager查看已安装的源应用程序ID
  • 使用一些应用程序ID命名约定(如果您将是所有源应用程序的开发人员),并使用PackageManager查看哪些已安装的应用程序遵守该约定
  • 使用PackageManagerqueryBroadcastReceivers()查看哪些应用为某些已知的操作字符串实现了接收器
  • 使用PackageManager遍历所有已安装的应用程序,并查看其中有特定的<meta-data>条目

您可以使用SharedPreferenceMultiSelectListPreference或类似的UI,以允许用户取消选中他们不希望消费者应用使用的特定来源。

鉴于您正在计划将广播发送给消费者的源,您还需要在源应用中使用相同的基本流程来查看:

  • 安装了哪些消费者
  • 用户希望源应用与哪些消费者一起使用

鉴于来源知道合格的消费者,反之亦然,您可以使用多种IPC选项。

感觉大多数通信都是源->消费者。在这种情况下,让消息源使用广播是合理的。请记住,这些将需要是明确的广播:

  • 使用所需的操作字符串创建一个Intent
  • 遍历合格使用者的应用程序ID
    • setPackage()的副本上使用Intent使其与特定使用者相关联
    • 发送该副本的“广播”

如果我没错,大多数通信是源->消费者,那么使用来自消费者->源的广播来“唤醒”源并获取缓存的数据是合理的,如果这样做可以简化源的实现。定期更新广播可能与“发送缓存的事件”广播非常相似。

如果这两个广播之间存在实质性差异,以致在源或使用者上不会共享太多代码,则可以消除该方法的异步特性,并使用ContentProvider,源中有供消费者查询的提供程序。


恕我直言,您所有这方面的第一大问题就是隐私和安全性。这样的N方通信很难确保不会偶然发生N + 1方通信,其中+1是间谍软件。