首页 > 解决方案 > 是什么让 BroadcastReceiver 这么晚才得到它的意图?

问题描述

背景

我们有一个大型应用程序,它具有各种功能,使用多个库,并使用以下方式处理电话BroadcastReceiver

    <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手机开始响铃后的接收意图相当长的时间(3-5 秒)。

这是一个问题,因为应用程序需要立即处理电话。

我尝试并发现的

  1. 在 POC 中,它似乎工作得很好。即使在我的一个用于电话录音的存储库(此处BroadcastReceiver)上,如果我在其中添加日志而不是真正的逻辑,我也可以看到它立即得到处理。我什至将大型应用程序的所有权限添加到我制作的这个示例应用程序中(并授予它们),它仍然可以正常工作。可悲的是,添加大型应用程序使用的库可能需要大量时间来添加和测试

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

  3. 我想这可能是因为我们使用了多索引。我试图禁用它,但它没有帮助。我认为它甚至不会影响它,因为我已经在 Pixel 2 上的 Android P 上进行了尝试。

  4. 我试图设置BroadcastReceiver. 尝试将其设置为 999 (这是允许的最大值),甚至设置为 2147483647 ,但这些都没有帮助。

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

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

  7. 我认为唯一的原因可能是应用程序使用的库。有很多,但我想知道什至在调用扩展 Application 的类之前会影响应用程序......遗憾的是,有这么多,需要花费大量时间将它们全部添加到 POC 项目中。我想我会这样做,但我想知道这是否真的是原因。

问题

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

  2. 为什么“内存使用”屏幕看起来如此不可靠并且与我在 IDE 的分析器上看到的相矛盾?这可能是迟到的意图(操作系统的巨大内存分配)的原因吗?


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

似乎更好,但问题是应用程序在电话响起后触发得太晚,因此问题仍然存在。

标签: androidbroadcastreceiverandroid-phone-call

解决方案


好吧,看来我错了,这个 Intent 可能会有点晚收到,这取决于操作系统,也可能取决于应用程序的轻量级。

我现在这样想的原因是,我注意到即使是 TrueCaller 也不总是立即出现。有时也可能需要很长时间。

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

在前台服务中意味着类似的东西:

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

我能说的是,如果应用程序有通知访问权限,它有很大的机会永远活着,所以它不需要前台服务。


推荐阅读