是什么让 BroadcastReceiver 这么晚才得到它的意图?

What could make a BroadcastReceiver to get its intents so late?

背景

我们有一个大型应用程序,它具有各种功能,使用多个库,并使用 BroadcastReceiver:

处理 phone 调用
    <receiver android:name="....PhoneBroadcastReceiver">
        <intent-filter >
            <action android:name="android.intent.action.PHONE_STATE"/>
        </intent-filter>
        <intent-filter >
            <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
        </intent-filter>
    </receiver>

问题

最近我注意到,如果我们使用最近的任务关闭应用程序,BroadcastReceiver 在 phone 开始响铃后的很长时间(3-5 秒)内接收到意图.

这是个问题,因为该应用需要立即处理 phone 个调用。

我已经尝试并发现了什么

  1. 在 POC 中,它似乎工作得很好。即使在我的一个用于 phone 通话记录的存储库 (here) 上,如果我在 BroadcastReceiver 中添加日志而不是真正的逻辑,我可以看到它得到了正确的处理离开。我什至将大型应用程序的所有权限添加到我制作(并授予它们)的这个示例应用程序中,它仍然运行良好。添加大型应用程序使用的库可能需要花费大量时间来添加和测试,遗憾的是

  2. 我在想,也许从应用程序(或MultiDexApplication,准确地说)扩展的class花费了太多时间,所以我在那里添加了一个日志( onCreate 的开头)。确实需要一点时间(一秒左右),但是log是过一会才显示出来的,和BroadcastReceiver的log差别很小。所以这个问题应该是由比应用程序或 BroadcastReceiver.

  3. 更深层次的原因引起的
  4. 我想可能是因为我们使用了 multi-dexing。我试图禁用它,但没有帮助。我认为它甚至不会影响它,因为我已经在 Pixel 2 上的 Android P 上尝试过。

  5. 我尝试设置BroadcastReceiver的优先级。试图将其设置为 999(即 max allowed),甚至设置为 2147483647 ,但其中 none 有所帮助。

  6. 我想也许 OS 正在为应用程序分配大量内存,这可能需要一些时间,但我知道其他监听相同 Intents 的应用程序(例如作为 TrueCaller)即使在我从最近的任务中关闭应用程序后也能正常工作。我还测试了应用程序使用了多少内存,以及 TrueCaller 使用了多少内存。该应用程序在我的 Pixel 2 上平均使用 33MB 的总内存,而 TrueCaller 使用 2MB。我从 "memory usage" 的开发者选项屏幕获得了这些值。奇怪的是它告诉最大 RAM 使用量很大(大约 1GB),即使从头开始启动应用程序也是如此,但我从未在分析器中看到它,甚至没有接近(大约 200MB)。我认为这个屏幕不是检查内存使用情况的可靠方法。

  7. 我认为将应用程序排除在电池优化之外可能会有帮助,但事实并非如此。即使是向用户请求此功能的 TrueCaller,在这种情况下也并不真正需要它。它在那里没有设置它就可以正常工作。

  8. 我认为唯一可能的原因是应用程序使用的库。还有很多,但我想知道在调用扩展应用程序的 class 之前,什么会影响应用程序......遗憾的是,有太多的东西需要很多时间才能将它们全部添加到 POC 中项目。我想我会做的,但我想知道这是否真的是原因。

问题

  1. 什么可能会影响 BroadcastReceiver 这么晚才得到它的意图?这可能是我提到的事情之一吗?

  2. 为什么 "memory usage" 屏幕看起来如此不可靠并且与我在 IDE 的分析器上看到的相矛盾?这可能是 Intent 延迟的原因(OS 的巨大内存分配)?


编辑:我注意到一些库初始化在扩展应用程序的 class 的 onCreate 调用中花费了太多时间,所以我把它们中的一些放在后台线程中,还有一些我'我们甚至删除了。

似乎好多了,但问题是应用程序在 phone 响铃后触发得太迟,所以问题仍然存在。

好吧,看来我错了,这个 Intent 可能会晚一点收到,这取决于 OS 也可能取决于应用程序有多轻。

我现在这样想的原因是,我注意到即使是 TrueCaller 也不总是立即出现。有时这也会花费他们很长时间。

所以我认为唯一可以安全地听取这些意图的方法是以编程方式而不是通过清单。

前台服务中的意思类似:

        telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        telephonyManager!!.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE)

我能说的是,如果应用程序已授予通知访问权限,则它很有可能一直处于活动状态,因此不需要前台服务。