Android 开机广播接收不到

还有点需要考虑,apk的AndroidManifest.xml的组件信息是何时导入的,如果广播发出来的时候,我们的apk的receiver信息还没被PackageManagerService导入,一样是收不到的,这个坑我自己在Android P上面踩到了。2.广播3,广播4和比广播1晚5s发送的广播2,此时我们的apk的AndroidManifest.xml已经导入完毕,所以receivers得到的结果是正确的,size是1,对应我们的apk。但凡稍有些经验的开发者都知道,这个广播很慢,非常慢。
摘要由CSDN通过智能技术生成

Android 开机广播接收不到
背景
一般来说,我们都是用的监听android.intent.action.BOOT_COMPLETED。

但凡稍有些经验的开发者都知道,这个广播很慢,非常慢。因为它是一个有序广播,根据优先级来的,而且监听这个广播的apk又非常多。打个log感受一下,这个广播开始到结束在我司的机器上持续了30s!

在这里插入图片描述

关键是你把优先级调高了,即便你是前几个收到android.intent.action.BOOT_COMPLETED的,从开机动画走完,锁屏界面跳出来 到你的apk收到这个广播,大概还是有个5s左右的时间。

原因是android.intent.action.BOOT_COMPLETED发出来的时候就不是最早的。它前面还有

android.intent.action.LOCKED_BOOT_COMPLETED,android.intent.action.MEDIA_MOUNTED等。

要等这几个广播处理完了,才轮到android.intent.action.BOOT_COMPLETED。

在这里插入图片描述
我们的目的是让我们的apk尽早起来(一般都是收了广播,然后receiver的onReceive去start我们的service)。

那么我们有以下几种处理办法:

1.接收android.intent.action.BOOT_COMPLETED,调高优先级。

2.接收android.intent.action.MEDIA_MOUNTED,因为这个广播一方面比android.intent.action.BOOT_COMPLETED发送的要早,一方面监听它的apk比较少。

3.直接在AMS里面去start我们的service,过于粗暴且不通用。

4.自定义开机广播,这样监听这个广播的apk只有我们自己,并且尽早的发出这个广播。

我们要考虑的问题:

1.如果监听android.intent.action.MEDIA_MOUNTED,这个广播是挂载存储的时候发的,开机的时候挂载到手机的存储区(storage/emulated/0)会发一下,后面如果插入sdcard也会发。要评估多次触发广播是否会对自己的apk业务逻辑造成影响(以免自己本来stop了的service又被叫起来)。

2.自定义开机广播,这个广播发出来的时机。需要考虑system是否Ready,这个一般都达到了,大家写也会注意。还有点需要考虑,apk的AndroidManifest.xml的组件信息是何时导入的,如果广播发出来的时候,我们的apk的receiver信息还没被PackageManagerService导入,一样是收不到的,这个坑我自己在Android P上面踩到了。后面会详细说。

先直接上可行的结论:
Android O自定义开机广播
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
finishBooting()方法里:

UserController.sendBootCompletedLocked(
        new IIntentReceiver.Stub() {
   
            @Override
            public void performReceive(Intent intent, int resultCode,
                    String data, Bundle extras, boolean ordered,
                    boolean sticky, int sendingUser) {
   
                synchronized (ActivityManagerService.this) {
   
                    requestPssAllProcsLocked(SystemClock.uptimeMillis(),
                            true, false);
                }
            }
        });
scheduleStartProfilesLocked();
//potter add
Intent customIntent=new Intent("com.honeywell.intent.action.BOOT_COMPLETED");
customIntent.setPackage("com.honeywell.ezreceiver");
mContext.sendBroadcast(customIntent);
//potter end

有人可能会问,这样只有一个apk能收到,如何让所有apk都收到。按下面这么写即可。

//potter add
Intent customIntent=new Intent("com.honeywell.intent.action.BOOT_COMPLETED");
customIntent. addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext.sendBroadcast(customIntent);
//potter end

可能又有人会问,这样apk收到的顺序没法控制,那么按下面这么写:

//potter add
Intent customIntent=new Intent("com.honeywell.intent.action.BOOT_COMPLETED");
customIntent. addFlags(Intent.FLAG_RECEIVER_NO_ABORT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext. sendOrderedBroadcast(intent, null);
//potter end

我们多给加上一个Intent.FLAG_RECEIVER_NO_ABORT的Flag,让这个有序广播不能被abort掉。实际上系统里面的android.intent.action.BOOT_COMPLETED这个广播就是这两个flag。

这么写,功能已经实现了。但是从设计的角度很不好。因为这么写作为一个在System发出去的广播并没有加权限,这是不符合android的规范的。

我们追下源码:
sendBroadcast>>>
ContextImpl.java的sendBroadcast>>>
ActivityManagerService.java的broadcastIntent>>>
ActivityManagerService.java的broadcastIntentLocked

在AMS的broadcastIntentLocked方法里的


                
  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值