Android: registerReceiver代码实现
1. 用户接口registerReceiver
frameworks/base/core/java/android/content/ContextWrapper.java
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
frameworks/base/core/java/android/app/ContextImpl.java
@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);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler, int flags) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), flags);
}
class ContextImpl extends Context {
......
@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, filter, broadcastPermission,
scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
// mPackageInfo是一个LoadedApk实例,它是用来负责处理广播的接收的
// context 是通过调用函数getOuterContext得到的
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
// mMainThread.getHandler来获得一个Handler了,
//这个Hanlder是后面用来分发ActivityManagerService发送过的广播用的。
// 这里的成员变量mMainThread是一个ActivityThread实例
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
......
}
}
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) {
return null;
}
}
......
}
// BroadcastReceiver
frameworks/base/core/java/android/content/BroadcastReceiver.java
// getHandler()
public final class ActivityThread {
......
final H mH = new H();
private final class H extends Handler {
......
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
}
......
}
......
}
......
final Handler getHandler() {
return mH;
}
......
}
//
frameworks/base/core/java/android/app/LoadedApk.java
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) {
// ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<>();
//由context获得ArrayMap<BroadcastReceiver, ReceiverDispatcher>>
//由BroadcastReceiver获得ReceiverDispatcher
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
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;
//获得后就会把它传给ActivityManagerService,以便接收广播
return rd.getIIntentReceiver();
}
}
static final class ReceiverDispatcher {
//InnerReceiver实例,这是一个Binder对象,实现了IIntentReceiver接口,
//可以通过ReceiverDispatcher.getIIntentReceiver函数来获得,
//获得后就会把它传给ActivityManagerService,以便接收广播。
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
......
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
......
}
......
}
......
final IIntentReceiver.Stub mIIntentReceiver;
final Handler mActivityThread;
......
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
......
mIIntentReceiver = new InnerReceiver(this, !registered);
mActivityThread = activityThread;
......
}
......
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
}
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public Intent registerReceiver(IApplicationThread caller, IIntentReceiver receiver, IntentFilter filter, String permission) {
synchronized(this) {
// 函数首先是获得调用registerReceiver函数的应用程序进程记录块
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
......
}
}
List allSticky = null;
// Look for any matching sticky broadcasts...
Iterator actions = filter.actionsIterator();
if (actions != null) {
while (actions.hasNext()) {
String action = (String)actions.next();
allSticky = getStickiesLocked(action, filter, allSticky);
}
} else {
......
}
//广播接收器receiver保存一个ReceiverList列表中,这个列表的宿主进程是rl.app,这里就是MainActivity所在的进程了,
//在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,
//专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在
//ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器的
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp,
Binder.getCallingPid(),
Binder.getCallingUid(), receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
......
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//创建一个BroadcastFilter来把广播接收器列表rl和filter关联起来,
//然后保存在ActivityManagerService中的成员变量mReceiverResolver中去
BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
rl.add(bf);
......
mReceiverResolver.addFilter(bf);
}
}
......
}
Android: registerReceiver代码实现相关推荐
- Android APP代码执行历史漏洞与攻击面分析
文章目录 前言 错误的反射调用 漏洞根源分析 漏洞防御建议 反射调用思考 CVE-2020-8913 漏洞根源分析 动态加载Dex "寄生兽"漏洞 TikTok APP漏洞 代码执 ...
- android命令行工具 混淆,Android 混淆代码学习以及Android加密工具--APKProtect的使用ZZ...
一:情景分析 有时候看到其他应用App的一些效果很炫,或者是功能实现很好就想着参考参考,于是乎,下载APK----反编译APK---查看源码....,但是悲剧来了....源码都是些a,b,c...等等 ...
- 黑客破译android开发代码真就那么容易?
2019独角兽企业重金招聘Python工程师标准>>> 很多程序员辛辛苦苦开发出的android开发代码,很容易就被黑客翻译了. Google似乎也发现了这个问题,从SDK2.3开始 ...
- android 共享代码,Android团队成员间的代码共享!(Git+Github版)
原创,转载请说明出处. 一. 这篇文章要解决什么问题,能学习到什么? 在android团队的开发中,少不了与队员之间的合作.为了避免我们傻瓜式地复制粘贴对方的负责的那部分功能代码,我们可以用svn或者 ...
- Android实用代码七段(五)
1.展开.收起状态栏 public static final void collapseStatusBar(Context ctx) { Object sbservice = ctx. ...
- Android实用代码(不定期更新)
Android实用代码七段(一) 一抹火焰 整理(不定期更新) 前言 这里积累了一些不常见确又很实用的代码,每收集7条更新一次,希望能对大家有用. 声明: 欢迎转载,但请保留文章原始出处:) 博客园 ...
- Android Studio 代码自动提示无效
Android Studio代码自动提示无效(not available in Power Save mode)的解决办法 问题描述: 今天用Android studio敲代码,突然间就没有代码提示了 ...
- 高通android开源代码下载
高通android开源代码下载 开源网站https://www.codeaurora.org/projects/all-active-projects/android-msm,选择wiki,在Wiki ...
- 论初次修改 Android framework 代码
点击打开链接 论初次修改 Android framework 代码 背景 公司产品需求,需要修改系统 framework 层的部分界面显示,包括声音调节.亮度调节.长按电源关机等. 准备 我并不是白手 ...
最新文章
- 百度搜索结果图文标识规则分析
- BZOJ 1132 [POI2008]Tro(极角排序)
- 【Java】使用Java调用Python的四种方法
- 82%开源软件兼容Windows
- kmap_atomic的细节以及改进
- Spring Boot ES 实战,直接拿来用!
- log4j.xml配置示例
- chrome浏览器历史版本
- 计算机基础cpu知识,CPU基础知识大全详解
- 多元统计分析朱建平pdf_应用多元统计分析课后答案朱建平版
- 微信朋友圈设计方案简述
- 用HTML创建幻灯片
- CTF-密码学-培根密码
- 超人工智能语音合成系统问世
- CSS3实现折角效果
- 数据挖掘—GEO,TCGA,Oncomine联合(三)GEO数据的下载和数据质量分析
- css换行文字隐藏,css 文本换行 文本溢出隐藏用省略号表示剩下内容
- 抢红包: 红包过期失效案例
- ps cs6 mac破解方法
- 飞飞cms添加广告html,飞飞影视cms-飞飞cms免费影视站程序
热门文章
- ABB机器人自制单轴偏移函数
- 基于MOS的防反接电路
- sts写java没有自动补齐,STS 创建 Maven 项目填坑
- SpringBoot合集笔记
- JDK之伪分享的情况下该使用填充还是@Contended
- 0x000000f怎么修复 win10_0xc000000f怎么修复,教你u盘重装win10系统出现0xc000000f的修复方法...
- layui radio 回显
- [android]不解锁刷机
- jquery - 定义二维数组
- 数据库可用于左右填充0的函数--->LPAD与RPAD