我目前正在研究一种体系结构,以在应用程序之间传递交通消息(“ 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风格上,通过隐式广播唤醒应用程序也无法按预期方式工作(我正在开发的设备也具有该限制)。
让使用者从所有源中检索所有当前活动的消息(即使它们没有运行)的良好机制是什么?实施内容提供程序看起来有点过大,那么还有哪些其他选择可用?
最佳答案
您的消费者应用程序将需要知道:
安装了哪些源
用户希望消费者应用使用哪些来源的子集(因为用户可能不希望全部使用)
知道安装哪些源的可能方法包括:
遍历已知可能的源应用程序ID的列表,并使用PackageManager
查看已安装的源ID
使用某些应用程序ID命名约定(如果您将是所有源应用程序的开发人员),并使用PackageManager
查看哪些已安装的应用程序遵守该约定
使用PackageManager
和queryBroadcastReceivers()
查看哪些应用为某些已知操作字符串实现了接收器
使用PackageManager
遍历所有已安装的应用程序,并查看哪些具有特定的<meta-data>
条目
您可以使用SharedPreference
和MultiSelectListPreference
或某些类似的UI,以允许用户取消选中他们不希望消费者应用使用的特定来源。
鉴于您正在计划将广播发送给消费者的源,因此在源应用程序中还需要相同的基本流程,以查看:
安装了哪些消费者
用户希望源应用程序与哪些消费者一起使用?
假定来源知道合格的消费者,反之亦然,则您可以选择各种IPC。
感觉大多数通信都是源->消费者。在这种情况下,让消息源使用广播是合理的。请记住,这些将需要显式广播:
用所需的操作字符串创建一个Intent
遍历合格使用者的应用程序ID
在setPackage()
的副本上使用Intent
将其与特定使用者相关联
发送该副本的“广播”
如果我没错,大多数通信是源->消费者,那么使用来自消费者->源的广播来“唤醒”源并获取缓存的数据是合理的,如果这样做可以简化源的实现。定期更新广播可能与“发送缓存的事件”广播非常相似。
如果这两个广播之间存在实质性差异,以致在源或使用者上不会共享太多代码,则可以消除该方法的异步特性,并使用ContentProvider
,其中源具有一个消费者可以查询的提供者。
恕我直言,您所有这些的第一大问题是隐私和安全性。这样的N方通信很难确保N + 1方通信不是偶然的,+ 1是一种间谍软件。