Android插件化-Broadcast篇,2024年最新安卓面试自我介绍

简介: Android插件化-Broadcast篇,2024年最新安卓面试自我介绍
public static abstract class Component {
public final ArrayList intents;
public final String className;
public Bundle metaData;
public Package owner;
/** The order of this component in relation to its peers */
public int order;
ComponentName componentName;
String componentShortName;
//其他方法实现

注意对于静态注册在插件AndroidManifest.xml文件中的Receiver,宿主需要知道Receiver的className以及其对应注册的Action,这样在宿主中才能实现广播的中转;因此整个解析过程也就需要解析出广播的ClassName以及其注册的Action就OK了。

对于ClassName在Component已经出现,而对于Action我们则继续看Component类中的intents这个列表,该列表中所存储的对象对应的类集成至IntentInfo,因此我们还需要继续往上看才行。

public static abstract class IntentInfo extends IntentFilter {
public boolean hasDefault;
// 其他属性以及方法

而该内部类又继承至类IntentFilter,这里IntentFilter则不再是PackageParser类的内部类了,它就是我们在动态注册Reciver所用到的IntentFilter;而在IntentFilter类中我们则能够直接通过其mActions属性拿到当前ClasName对应Receiver所静态注册的Action了。

2、插件中静态注册广播解析实现

接下来就是通过反射的方式调用PackageParser的parsePackage获取到PackageParser$Package对象,接着就是一步一步的对该对象进行解析了。对应源码如下:

public static void parsePackage(String apkPath) {
try {
//根据插件本地存储的文件地址生成对应的文件
File file = new File(apkPath);
if (!file.exists()) {
Log.i(TAG, “parse plugin receiver apk not exist”);
return;
}
Log.i(TAG, "parse package path is " + apkPath);
//获取到PackageParser类对象
Class cls = Class.forName(“android.content.pm.PackageParser”);
Object packageParserObj = RefInvoke.createObject(cls, null, null);
if (null == packageParserObj) {
Log.i(TAG, “parse package create packageParser object failed”);
return;
}
//调用parsePackage方法
Object packageObj = RefInvoke.on(packageParserObj, “parsePackage”, new Class[]{File.class, int.class})
.invoke(file, PackageManager.GET_RECEIVERS);
if (null == packageObj) {
Log.i(TAG, “parse package get packageObj failed”);
return;
}
//获取PackageParser$Package对象中的receivers列表
List receivers = (List) RefInvoke.getFieldValue(RefInvoke.getField(packageObj.getClass(), “receivers”), packageObj);
if (null == receivers) {
Log.i(TAG, “parse package get receivers failed”);
return;
}
//遍历receivers列表获取AndroidManifest.xml文件中所注册的Receiver信息
for (Object receiver : receivers) {
parseAction(receiver, apkPath);
}
} catch (Exception e) {
Log.i(TAG, "parse package failed " + e);
}
}

上面代码就是通过反射的方式调用PackageParser的parsePackage方法,并遍历获取到的receivers列表。接下来就就是对receivers列表中的每个Receiver相关信息进行解析了。

private static void parseAction(Object receiver, String path) {
try {
//根据反射获取到PackageParserC o m p o n e n t 对象中的 i n t e n t s 列表 C l a s s < ? > c l s = R e f I n v o k e . g e t C l a s s ( " a n d r o i d . c o n t e n t . p m . P a c k a g e P a r s e r Component对象中的intents列表 Class cls = RefInvoke.getClass("android.content.pm.PackageParserComponent对象中的intents列表Class<?>cls=RefInvoke.getClass("android.content.pm.PackageParserComponent");
ArrayList intents = (ArrayList) RefInvoke.getFieldValue(RefInvoke.getField(cls, “intents”), receiver);
if (null == intents || 0 == intents.size()) {
return;
}
//获取该Receiver对应的ClassName
String clsName = (String) RefInvoke.getFieldValue(RefInvoke.getField(cls, “className”), receiver);
Log.i(TAG, "parseAction current receiver name is " + clsName);
//根据插件所在文件地址生成对应的ClassLoader并根据获取到的ClassName生成对应的对象
Object receiverObj = creatReceiverObj(clsName, path);
if (null == receiverObj) {
Log.i(TAG, “parseAction create receiver obj failed”);
return;
}
//接着就是遍历该Receiver中所注册的Action并存储在内存中以便宿主在接收到对应Action的广播之后能够直接进行转发
for (IntentFilter intentFilter : intents) {
Class intentFilterCls = RefInvoke.getClass(“android.content.IntentFilter”);
Log.i(TAG, "field: " + RefInvoke.getField(intentFilterCls, “mActions”));
List actions = (List) RefInvoke.getFieldValue(RefInvoke.getField(intentFilterCls, “mActions”), intentFilter);
for (String action : actions) {
registerActionToReceiver(action, receiverObj);
}
}
} catch (Exception e) {
Log.i(TAG, "parseAction failed " + e);
}
}
private static Object creatReceiverObj(String clsName, String path) {
try {
DexClassLoader dexClassLoader = DeHostDexClassloader.getInstance().getDexClassLoader(DePluginApplication.getContext(), path);
Class cls = dexClassLoader.loadClass(clsName);
return RefInvoke.createObject(cls, null, null);
} catch (Exception e) {
Log.i(TAG, "createReceiverObj failed " + e.getCause());
}
return null;
}


相关文章
|
7月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
762 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
|
JavaScript 前端开发 Android开发
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
491 13
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
7月前
|
缓存 Unix Android开发
Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡
Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡
735 8
|
9月前
|
存储 机器学习/深度学习 API
Android API Level 到底是什么?和安卓什么关系?应用发布如何知道自己的版本?优雅草卓伊凡
Android API Level 到底是什么?和安卓什么关系?应用发布如何知道自己的版本?优雅草卓伊凡
1366 31
Android API Level 到底是什么?和安卓什么关系?应用发布如何知道自己的版本?优雅草卓伊凡
|
10月前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
435 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
540 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
数据采集 JavaScript Android开发
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
598 7
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
1904 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
人机交互 Android开发 iOS开发
|
程序员 Android开发 开发者

热门文章

最新文章