建议阅读本文之前先阅读死磕Android_Service启动流程分析(一),因为有些内容是一致的,方便融合.
早期的时候,广播的特性被各种流氓APP利用.好多好多流氓APP监听比如打电话,收发短信,有些流氓APP甚至直接拦截短信,,当然那个年代早已是过去式了,应该是4.4以前吧,反正以前那会儿挺乱的.现在好多了,想要读取短信内容,难上加难,更不能拦截短信.除非是将APP设置成了默认应用,可以收到短信通知,而且也不能拦截这条广播.以前那会儿即使进程被杀了,只要注册了静态广播,都是能收到的.某些APP收到广播后,就自启,自启后就干些流氓的事情....
特别是Android 8.0之后,大部分的静态广播差不多都失效了.所以我们还是尽量用动态广播比较好,需要的时候注册,不需要的时候解注册.如果只是应用内自己和自己通信,那是么可以使用LocalBroadcastManager的,通信安全.
定义一个简单的广播
class StaticReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.e("xfhy", "我收到消息了")
}
}
下面是静态注册
需要到清单文件中进行注册
<receiver
android:name=".StaticReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.xfhy.staticreceiver"/>
</intent-filter>
</receiver>
如果是动态注册,那么需要注册和解注册.
//注册
val intentFilter = IntentFilter()
registerReceiver(myBroadcast, intentFilter)
//解注册
unregisterReceiver(myBroadcast)
注册之后,就可以发广播了
val intent = Intent(applicationContext, StaticReceiver::class.java)
intent.action = "com.xfhy.staticreceiver"
sendBroadcast(intent)
由于现在基本都用动态广播了(不知道是不是....因为Android 8.0的限制),所以直接讲解动态广播的注册方式.静态注册的方式是通过PMS在应用安装的时候就注册好了,其他3个组件也是.
事不宜迟,我们从registerReceiver方法开始深入,来到ContextWrapper的registerReceiver方法.我们知道Activity是继承了ContextWrapper的.
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextWrapper几乎是不干实事的,全是交给mBase去做.而mBase是ContextImpl,在Service启动那篇文章中已讲解.
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
最终会调用registerReceiverInternal方法.而这里有一个IIntentReceiver对象,需要注意.由于在注册的时候是向AMS发起请求需要注册,而BroadcastReceiver是不能进行跨进程传输的,所以需要一个介质.而IIntentReceiver就是专门拿来与AMS通信的,它是一个Binder对象.这里的ReceiverDispatcher和Service绑定流程那里的ServiceDispatcher简直一模一样.ReceiverDispatcher里面有BroadcastReceiver和IIntentReceiver对象,都是在ReceiverDispatcher的构造方法就初始化好了,当收到广播的时候直接调用BroadcastReceiver对象的onReceive方法,简单方便.
来来来,我们看下LoadedApk的getReceiverDispatcher方法
//缓存
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<>();
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
//如果是已经注册 有缓存则用缓存
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
//第一次
if (rd == null) {
//ReceiverDispatcher初始化,这里会将BroadcastReceiver放进去,然后构造方法会将InnerReceiver(用来跨进程通信的)初始化
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
谷歌工程师写的代码就是牛批,原理几乎一毛一样.
好了,当IIntentReceiver创建好了之后,就可以和AMS进行通信了.上面的ActivityManager.getService()就是AMS哈,在之前的文章经常提到.来到AMS的registerReceiver方法
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
......
mRegisteredReceivers.put(receiver.asBinder(), rl);
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
mReceiverResolver.addFilter(bf);
}
上面这个过程会把InnerReceiver(待会儿需要拿来跨进程通信的)和IntentFilter存起来,其实广播的注册就完成了.
通过sendBroadcast方法发送广播,其实就是在调用的父类ContextWrapper的sendBroadcast方法,之前我们分析过,ContextWrapper本身是不干啥实事的,它其实是调用的ContextImpl的sendBroadcast方法.
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
}
ActivityManager.getService()是AMS哈,分析过很多次了.这里调用了AMS的broadcastIntent方法
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
上面最核心的就是broadcastIntentLocked方法了,当我看到这个方法的行数时,我傻眼了,,,大家感受一下.600多行的代码,,,,
我们挑选核心的代码来分析
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
// By default broadcasts do not go to stopped apps.
//已经停止的APP 无法收到广播
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
//将符合条件的广播,添加到BroadcastQueue中,然后进行发送
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
我们在源码中可以看到,已经停止了的APP是收不到广播的.然后就是经过一系列的复杂的筛选过程,将符合条件的广播添加到 BroadcastQueue中,然后进行发送广播.
public void scheduleBroadcastsLocked() {
......
//发送了一个消息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
}
private final class BroadcastHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
}
}
}
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
processNextBroadcastLocked(fromMsg, false);
}
}
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
......
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
//发送广播这里的r是BroadcastRecord,这个方法里面会调用performReceiveLocked方法
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
}
}
//具体的发送过程
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null) {
if (app.thread != null) {
try {
//调用ApplicationThread中的scheduleRegisteredReceiver方法
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} catch (RemoteException ex) {
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
+ " (pid " + app.pid + "). Crashing it.");
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
辗转反侧,会去调用ApplicationThread的scheduleRegisteredReceiver方法,
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
注意,上面的IIntentReceiver是ReceiverDispatcher中的InnerReceiver对象,这个对象是拿来跨进程通信的.直接调用了InnerReceiver的performReceive方法,来看一下
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
其实performReceive就是调用ReceiverDispatcher的performReceive,ReceiverDispatcher是InnerReceiver和BroadcastReceiver的桥梁,因为它里面有两者的引用,可以和方便地进行调用其方法.下面是ReceiverDispatcher的实现
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
//注意这句代码 mActivityThread是一个Handler,主线程的Handler,
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
performReceice里面就是利用主线程中的Handler运行一个Runnable.内容如下:
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
mCurIntent = null;
mDispatched = true;
mPreviousRunStacktrace = new Throwable("Previous stacktrace");
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
//注意了,BroadcastReceiver是在这个时候进行构建的,构建之后立刻调用它的onReceive方法,注意这是在主线程中调用的
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
};
}
可以看到,BroadcastReceiver也是通过反射构建出来的,构建出来之后调用它的onReceive方法,并且是在主线程中调用的.
到这里,广播的发送和接收都已讲解完毕.