android 插件话加载,Android插件化(一) 动态加载技术

16284037c223ec56b18aaecf5ff37f0f.png

豆芽图片20171130151459511.png

app 与loutillib两个模块没有任何的依耐关系,在Module App中,我们想调用Loutillib中的LogUitl输出一条log。

所以我们采取dexClassLoader来加载这个jar

第一步:

首先我们将logutil这个module 依赖主app 然后运行下,这是时候会生成class.jar

然后在logutil中添加如下代码: 将class.jar重新命名下log.jar

task makeJar(type:Copy){

delete ‘build/libs/log.jar’

from(‘build/intermediates/bundles/release/’)

into(‘build/libs/’)

include(‘classes.jar’)

rename (‘classes.jar’, ‘log.jar’)

exclude(‘test/’,‘BuildConfig.class’,‘R.class’)

exclude{it.name.startsWith(‘R$’);}

}

makeJar.dependsOn(build)

上面配置好gradle 环境变量后,就可以再终端执行: gradlew makeJar

注意,这个jar还不能被加载,这个是基于class的jar,Dalvik虚拟机加载的是dex字节码,所以需要将class转化为dex字节码。这个需要用到dx命令,这个可以在Android\sdk\build-tools\23.0.0中找到,把log.jar拷贝到这个目录下,执行

dx --dex --output=new_log.jar log.jar

生成新的jar 然后push 到sdcard中

adb push new_log.jar sdcard/

以上准备工作 做好了之后, 第二步就开始撸DexClassLoader的代码了。

第二步:直接贴上代码,利用java 类加载

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

//动态加载dex文件 这里是个jar 包里面的方法

public void start(View view) {

//dex解压释放后的目录

final File dexOutPutDir = getDir(“dex”, 0);

//dex所在目录

final String dexPath = Environment.getExternalStorageDirectory().toString() + File.separator + “new_log.jar”;

//第一个参数:是dex压缩文件的路径

//第二个参数:是dex解压缩后存放的目录

//第三个参数:是C/C++依赖的本地库文件目录,可以为null

//第四个参数:是上一级的类加载器

DexClassLoader classLoader = new DexClassLoader(dexPath, dexOutPutDir.getAbsolutePath(), null, getClassLoader());

try {

final Class> loadClazz = classLoader.loadClass(“plugin.charles.com.logutil.LogUitl”);

final Object o = loadClazz.newInstance();

final Method printLogMethod = loadClazz.getDeclaredMethod(“printLog”);

printLogMethod.setAccessible(true);

printLogMethod.invoke(o);

} catch (Exception e) {

e.printStackTrace();

}

}

}

下面介绍的是动态加载未安装的apk.然后读取apk中图片,显示在宿主app中

1.首先准备换肤的apk

skindemo-debug.apk

skindemo2-debug.apk

这2个apk中都有一张图片,然后我们push这两个apk到sdcard中就可以

资源加载问题,怎么通过Resources 加载另外一个apk中的图片

/**

* 获取AssetManager 用来加载插件资源

*

* @param pFilePath 插件的路径

* @return

*/

private AssetManager createAssetManager(String pFilePath) {

try {

final AssetManager assetManager = AssetManager.class.newInstance();

final Class> assetManagerClazz = Class.forName(“android.content.res.AssetManager”);

final Method addAssetPathMethod = assetManagerClazz.getDeclaredMethod(“addAssetPath”, String.class);

addAssetPathMethod.setAccessible(true);

addAssetPathMethod.invoke(assetManager, pFilePath);

return assetManager;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

//这个Resources就可以加载非宿主apk中的资源

private Resources createResources(String pFilePath) {

final AssetManager assetManager = createAssetManager(pFilePath);

Resources superRes = this.getResources();

return new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());

}

3.宿主apk,动态换肤的点击事件代码

private boolean mChange = false;

private String skinType = “”;

private int APK_TYPE;

/**

* 替换bg

*/

public void replace(View view) {

if (!mChange) {

skinType = “skindemo-debug.apk”;

APK_TYPE = 1;

mChange = true;

} else {

skinType = “skindemo2-debug.apk”;

APK_TYPE = 2;

mChange = false;

}

final String path = Environment.getExternalStorageDirectory() + File.separator + skinType;

final String pkgName = getUninstallApkPkgName(this, path);

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值