广播Intent和广播接收器BroadcastReceiver,是大家android开发用的特别多的二个控件。
那如何从系统角度看待广播和广播接收器呢?
对于静态注册BroadcastReceiver和动态注册的BroadcastReceiver是如何回调其onReceive方法呢?
此文章以Android13版本为例,试浅分析之。
对于直接在AndroidManifest.xml静态注册的广播接收器BootReceiver,其回调onReceive过程为:
com.android.server.BootReceiver.onReceive(BootReceiver.java:162)
android.app.ActivityThread.handleReceiver(ActivityThread.java:4376)
android.app.ActivityThread.-$$Nest$mhandleReceiver(Unknown Source:0)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:2191)
其关键回调逻辑为:
ActivityThread.handleReceiver(ActivityThread.java:4376)
//定义BroadcastReceiver
BroadcastReceiver receiver;
......
receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
......
try {
if (localLOGV) Slog.v(
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + packageInfo.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
+ ", dir=" + packageInfo.getAppDir());
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
//回调定义BroadcastReceiver的onReceive方法
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
对于我们动态注册BroadcastReceiver的情况:
filter = new IntentFilter();
filter.addAction(intentDynatic);
registerReceiver(mReceiver, filter);
其回调onReceive过程为:
com.example.demo_test.MainActivity$1.onReceive(MainActivity.java:23)
android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$android-app-LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1809)
android.app.LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0.run(Unknown Source:2)
其关键回调逻辑为:
frameworks/base/core/java/android/app/LoadedApk.java
final class Args extends BroadcastReceiver.PendingResult {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
private Throwable mPreviousRunStacktrace; // To investigate b/37809561. STOPSHIP remove.
.....
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//需要在这,将intent,receiver,cl信息打印出来
receiver.onReceive(mContext, intent);
一般,我们使用以下命令读取设备的intent和BroadcastReceiver信息:
其主要有几种信息:
1.ReceiverList
* ReceiverList{8f08ba3 2124 com.mediatek.ims/1001/u0 remote:6585ed2}
app=2124:com.mediatek.ims/1001 pid=2124 uid=1001 user=0
Filter #0: BroadcastFilter{c094ea0}
Action: "com.mediatek.ims.ACTION_IMS_SIMULATE"
Action: "android.intent.action.BOOT_COMPLETED"
Action: "android.intent.action.SIM_STATE_CHANGED"
2.BroadcastFilter
android.intent.action.BOOT_COMPLETED:
BroadcastFilter{80935cb 1000/u-1 ReceiverList{62e389a 1350 system/1000/u-1 local:df35945}}
BroadcastFilter{337fb81 1000/u-1 ReceiverList{3a64b68 1350 system/1000/u-1 local:273de8b}}
BroadcastFilter{f263ee2 1000/u-1 ReceiverList{58e70c4 1350 system/1000/u-1 local:4d20fd7}}
BroadcastFilter{ecb6c7a 1000/u-1 ReceiverList{f7770a5 1350 system/1000/u-1 local:83b8e9c}}
BroadcastFilter{f11f0f9 10067/u0 ReceiverList{8b14bc0 1566 com.android.systemui/10067/u0 remote:8b3c943}}
BroadcastFilter{8c9b038 1001/u0 ReceiverList{145949b 1762 com.android.phone/1001/u0 remote:a5890aa}}
BroadcastFilter{9b1c005 1001/u0 ReceiverList{479ff7c 1762 com.android.phone/1001/u0 remote:6bc466f}}
BroadcastFilter{662abaa 1001/u0 ReceiverList{ed46e95 1762 com.android.phone/1001/u0 remote:7770e4c}}
BroadcastFilter{33a7c07 1001/u-1 ReceiverList{5740246 1762 com.android.phone/1001/u-1 remote:9e8ce21}}
BroadcastFilter{4712dcf 1001/u0 ReceiverList{ec2be2e 1762 com.android.phone/1001/u0 remote:71ee8a9}}
BroadcastFilter{3c5cb92 1001/u0 ReceiverList{3e1fd1d 1762 com.android.phone/1001/u0 remote:7ef21f4}}
BroadcastFilter{c094ea0 1001/u0 ReceiverList{8f08ba3 2124 com.mediatek.ims/1001/u0 remote:6585ed2}}
BroadcastFilter{9131711 1000/u0 ReceiverList{755b38 1350 system/1000/u0 local:f90b9b}}
3.BroadcastRecord
BroadcastRecord{684f7bd u0 android.intent.action.BOOT_COMPLETED} to user 0
Intent { act=android.intent.action.BOOT_COMPLETED flg=0x89000010 (has extras) }
extras: Bundle[{android.intent.extra.user_handle=0}]
caller=null null pid=1350 uid=1000
requiredPermissions=[android.permission.RECEIVE_BOOT_COMPLETED] appOp=-1
options=Bundle[{android.pendingIntent.backgroundActivityAllowed=true, android:broadcast.temporaryAppAllowlistReasonCode=200, android:broadcast.temporaryAppAllowlistDuration=20000, android:broadcast.temporaryAppAllowlistReason=, android:broadcast.temporaryAppAllowlistType=0}]
enqueueClockTime=2024-01-16 00:46:29.999 dispatchClockTime=2024-01-16 00:46:31.315
dispatchTime=-2h30m5s313ms (+1s316ms since enq) finishTime=-2h29m59s267ms (+6s46ms since disp)
resultTo=null resultCode=0 resultData=null
resultAbort=false ordered=true sticky=false initialSticky=false
nextReceiver=59 receiver=null
Deliver +962ms #0: (manifest)
priority=2147483647 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=false
ActivityInfo:
name=com.android.traceur.Receiver
packageName=com.android.traceur
enabled=true exported=true directBootAware=false
permission=android.permission.DUMP
launchMode=0 flags=0x20010000 privateFlags=0x0 theme=0x0
resizeMode=RESIZE_MODE_RESIZEABLE
knownActivityEmbeddingCerts={}
Deliver +2ms #1: BroadcastFilter{80935cb 1000/u-1 ReceiverList{62e389a 1350 system/1000/u-1 local:df35945}}
Deliver +55ms #2: BroadcastFilter{633e1f 10067/u0 ReceiverList{40c9dbe 1566 com.android.systemui/10067/u0 remote:c8d4c79}}