邮箱:Jack120612@163.com
我也是在进行学习和研究,有问题可以直接说
应该明确的问题
- 插件化是什么意思?
- 为什么要使用插件化的这种方式?
- 插件化的优劣?
根据上述问题我们就可以进行初步的了解了
- 插件顾名思义就是讲某一个东西拆分,App也一样可以拆分,原因有很多例如方法数的限制(65535是因为int本身的限制),app过大,性能损耗过于严重等等
- 插件化就是为了解决这类问题出现的
- 插件化的优点:模块解耦,动态升级,高效的并行开发,按需求进行加载等等
大概了解一下之后我们就开始进入基础的学习
需要的知识储备
- 反射相关
- ClassLoader的原理以及基本使用
- 代理模式等暂时就需要那么多,
废话不多说 直接上代码 先做出来点东西再去仔细研究代码
先来学习一下如何加载已经安装的apk的资源
整体的思路
- 首先我们需要先找到已经加载的apk(apk之间本身是互不相通的,我们可以在manifest节点上设置shareUsersId,这样我们的apk就可以在同一个运行区域内获取相关内容)
- 之后我们通过packageManager来获取已经安装的app
- 最重要的就是我们需要取到apk对应的Context或者Re
- 我们利用反射拿到资源id
- 通过Context拿到对应的资源就可以了
思路简单 实现起来也不是很难
大家看一下代码
ArrayList<InfoBean> labels = new ArrayList<>();
PackageManager pm = getPackageManager();
//拿到已经安装的列表
List<PackageInfo> installedPackages = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
for (PackageInfo info :
installedPackages) {
String packageName = info.packageName;
String sharedUserId = info.sharedUserId;
if(!TextUtils.isEmpty(sharedUserId)&&sharedUserId.equals("com.test.download")&&!packageName.equals(getPackageName())){
String label = pm.getApplicationLabel(info.applicationInfo).toString();
InfoBean bean = new InfoBean(label,packageName);
labels.add(bean);
}
}
//展示相关信息
showData(labels.get(0).label);
showData(labels.get(0).name);
//加载已经安装的apk文件并且找到其资源
//通过PathClassLoader进行加载
try {
//根据包名来创建对应的 参数一应用的lable 参数二第一个忽略警告第二个包含代码运行
Context pkgContext = this.createPackageContext(labels.get(0).label,CONTEXT_IGNORE_SECURITY|CONTEXT_INCLUDE_CODE);
//创建PathClassLoader该类加载器可以加载已经安装过的app 参数一路径 参数二父类加载器 一般都个ClassLoader.getSystemClassLoader()
PathClassLoader loader = new PathClassLoader(pkgContext.getPackageResourcePath(),ClassLoader.getSystemClassLoader());
//通过反射拿到drawable
Class<?> clazz = Class.forName(labels.get(0).label+".R$drawable", true, loader);
//拿到资源信息
Field about = clazz.getDeclaredField("about");
int res = about.getInt(R.drawable.class);
Drawable drawable = pkgContext.getResources().getDrawable(res);
drawListView.setBackground(drawable);
InfoBean只是一个简单信息的实体类,代码很简单,我就不贴出来了
说一下核心方法
this.createPackageContext()该方法会返回一个对应包的Context我们可以通过这个来得到资源文件
PathClassLoader loader = new PathClassLoader()我们可以通过加载器来加载已经安装过得apk
Field about = clazz.getDeclaredField(“about”);
int res = about.getInt(R.drawable.class);我们可以通过Field来获取图片资源pkgContext.getResources().getDrawable(res);利用已经获取到的
上下文来获取对应的图片资源
以上就是简单的实现
这个只是个demo练习学习用的
之后我还会写一篇基础的获取未安装的apk的资源
有什么问题可以问我