【问题标题】:Alternatives to implicit BroadcastReceiver?隐式广播接收器的替代方案?
【发布时间】:2018-06-24 13:54:26
【问题描述】:

我目前正在研究一种在应用程序之间传递流量消息(“Como-Monte Olimpino 和 Brogeda 之间的 A9 上的静态流量”)的架构。

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

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

多个来源和消费者可以同时处于活动状态。

当一个源接收到一条新消息时,它会发送一个广播 Intent,并将该消息作为额外的消息。消费者注册BroadcastReceiver 以获取这些消息。 (消息的有效负载通常为几百字节。)

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

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

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

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

什么是让消费者从所有来源检索所有当前活动消息的好机制,即使它们没有运行?实现内容提供者看起来有点矫枉过正,那么还有哪些其他选项可用?

【问题讨论】:

    标签: android polling android-broadcast


    【解决方案1】:

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

    • 安装了哪些源

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

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

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

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

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

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

    鉴于来源了解符合条件的消费者,反之亦然,您有多种 IPC 选项。

    感觉大部分通信都是来源 -> 消费者。在这种情况下,让源使用广播是合理的。请记住,这些必须是明确的广播:

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

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

    如果这两个广播之间存在显着差异,从而不会在源或消费者上共享很多代码,您可以消除该方法的异步性质并使用ContentProvider,其中source 有一个消费者可以查询的提供者。


    恕我直言,您在这方面的第一个问题是隐私和安全。像这样的 N 方通信很难确保它不是意外的 N+1 方通信,其中 +1 是一个间谍软件。

    【讨论】:

    • 选择来源是我不太关心的问题之一(通常我想要我能得到的所有交通信息)。该架构对任何人都是开放的,这使得包命名约定或详尽的应用程序列表变得不切实际。大多数通信确实是源->消费者(相反的情况通常每个消费者进程只发生一次)。我假设消费者不需要更新,除非它们正在运行,因此可以依赖上下文注册的接收器,这些广播可以是隐式的。隐私不是什么大问题。至于安全性,攻击者最多可以插入虚假的流量报告。
    • @user149408:“隐私不是什么大问题”——流氓消费者可以使用源数据获取用户的粗略位置,而无需获得系统权限。这可能不是您关心的问题;这可能是您的用户担心的问题。
    • 确实,如果轮询请求包含位置信息(尚未到位,但我最终需要添加)。它可能比粗略定位更不准确(消费者可能会要求用一个矩形包围路线,每条边缘可能有几百公里),但我可能想在获得许可的情况下保护它。
    • 另请参阅stackoverflow.com/questions/51012588/…,了解有关显式广播的详细信息。具体来说,一些 Android 发行版已经在较低版本中限制了隐式广播。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多