安卓里边可以用DexClassLoader实现动态加载dex文件,通过访问dex文件访问dex中封装的方法,如果dex文件本身还调用了native方法,也就间接实现了runtime调用native方法,这一流程主要包括:构建dex和so文件、在主工程添加动态调用代码、移除dex的module,将dex和so push到手机的指定路径

构建dex和so文件

首先在主工程里边新建一个名为testdepence的module,新建一个add类,在add类里边我们创建一个单例方法和一个native方法

public class Add {
private final static String TAG = "Add";
private static Add add = null;
static {
System.loadLibrary("anclivejni");
} public static Add getInstance(){
Log.d(TAG, "getInstance: ");
if (add == null){
add = new Add();
}
return add;
} public native void init(byte[] data); }

然后新建jni.cpp,实现init方法,这里我们就只是打印一个log


#define TAG "SXF"
#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)

extern "C" JNIEXPORT void JNICALL Java_com_example_testdepence_Add_init(JNIEnv
* env,
jobject thiz
,jbyteArray array) {
LOG("call init from native");
// TODO: implement init()
}

然后在gradle task里边选择 assembleRelease,运行,在testdepence module outputs/aar下会生成一个aar文件,把它的后缀改成zip,解压,得到classes.jar和so文件,然后用/your sdk dir/build-tools/plarform id下的dx工具将jar转换为dex文件,就ok了

## 在主工程添加动态调用代码

新建一个DynamicLoader类,添加使用DexClassLoader反射调用dex文件的代码

public class DynamicLoader {
private final static String TAG = "DanymicLoader";
private static Object handle;
/**
* 加载dex文件中的class,并调用其中的方法
* 这里由于是加载 jar文件,所以采用DexClassLoader
* 下面开始加载dex class
*/
private static Method getMethod(Context context,String methodName,Class<?>... methodArgs) {
File cacheFile = context.getCacheDir();
Log.d(TAG, "loadDexClass file path: " + cacheFile.getAbsolutePath());
String internalPath = cacheFile.getAbsolutePath() + File.separator + "classes.dex";
File desFile = new File(internalPath);
Method method = null;
if (desFile.exists()) {
DexClassLoader dexClassLoader = new DexClassLoader(internalPath//dex文件路径, cacheFile.getAbsolutePath()//dex文件解压路径, cacheFile.getAbsolutePath()//so的搜索路径, context.getClass().getClassLoader());
try {
Class<?> libClazz = dexClassLoader.loadClass("com.example.testdepence.Add");
Method getInstance = libClazz.getMethod("getInstance");
getInstance.setAccessible(true);
handle = getInstance.invoke(null);
if (handle ==null){
Log.d(TAG, "getInstance error handle is null !!! ");
}else {
Log.d(TAG, "getInstance success!!! ");
} method = libClazz.getMethod(methodName,methodArgs);
method.setAccessible(true); } catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "getMethod error: " + e.getMessage());
return method;
}
}else{
Log.d(TAG, "aar not exist!!!");
}
return method;
} public static int dynamicInit(Context context,byte[] data){
Method initHandle = getMethod(context,"init",byte[].class);
if (initHandle !=null && handle != null && data != null){
try {
initHandle.invoke(handle,data);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
return -1;
}
}
return 0;
}
}

然后在activity里边调用之

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DynamicLoader.dynamicInit(this,new byte[1024]);
}

之后在setting.gradle里边将testdepence里这个module移除,编译app,准备运行

将dex和so push到手机的指定路径

按照“internalPath//dex文件路径, cacheFile.getAbsolutePath()//dex文件解压路径, cacheFile.getAbsolutePath()//so的搜索路径”,将dex和so push到手机对应的目录,然后就可以打开app运行啦。

源码见github:https://github.com/gangmiangongjue/Android-Dynamic-Plugin-demo

好用的话请点个星星~不好用欢迎提case,谢谢

android 基于dex的插件化开发的更多相关文章

  1. Android基于代理的插件化思路分析

    前言 正常的App开发流程基本上是这样的:开发功能-->测试--->上线,上线后发现有大bug,紧急修复---->发新版本---->用户更新----->bug修复.从发现 ...

  2. JavaScript插件化开发

    大熊君JavaScript插件化开发 一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得昨天的那篇文章吗------这个系列的开篇(第一季).主要讲述了以“jQuery的方式如何开发插件”, 那 ...

  3. Android 插件化开发(二):加载外部Dex文件

    在学习Java反射的技术后,我们可以开始更深一步的探究插件化开发了.首先先讲一下Android App的打包流程,然后我们通过一个简单的例子 —— 实现插件化加载外部Dex来完成初级的插件化开发的探索 ...

  4. Android插件化开发

    客户端开发给人的印象往往是小巧,快速奔跑.但随着产品的发展,目前产生了大量的门户型客户端.功能模块持续集成,开发人员迅速增长.不同的开发小组开发不同的功能模块,甚至还有其他客户端集成进入.能做到功能模 ...

  5. 《Android插件化开发指南》面世

    本书在京东购买地址:https://item.jd.com/31178047689.html 本书Q群:389329264 (一)这是一本什么书 如果只把本书当作纯粹介绍Android插件化技术的书籍 ...

  6. Android插件化开发---执行未安装apk中的Service

    欢迎各位增加我的Android开发群[257053751​] 假设你还不知道什么叫插件化开发.那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从总体角度分析了一下 ...

  7. 【我的Android进阶之旅】Android插件化开发学习资料

    1.目前开源的插件开发框架大致有哪些? 1. 任玉刚 的 dynamic-load-apk Github 地址:https://github.com/singwhatiwanna/dynamic-lo ...

  8. 详解Android插件化开发-资源访问

    动态加载技术(也叫插件化技术),当项目越来越庞大的时候,我们通过插件化开发不仅可以减轻应用的内存和CPU占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块.     通常我们把安卓资源文件制 ...

  9. Android 插件化开发(四):插件化实现方案

    在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...

随机推荐

  1. 面向对象中static的理解(1)

    class 对象名字{ data members; static data members; function members; static function members; } 每创建一个对象, ...

  2. 使用apt安装docker

    使用apt安装docker # 更新数据源 apt-get update # 安装所需依赖 apt-get -y install apt-transport-https ca-certificates ...

  3. tomcat的log日志乱码解决方案

    Intellij idea Tomcat输出log中文乱码 配置tomcat在VM options添加-Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8 重启后控 ...

  4. CF1368E Ski Accidents

    读懂题是第一要素. 考虑把点集分割为:\(A,B,C\) 首先把所有入度为\(0\)的点加入\(A\) 然后对所有入边只来自\(A\)的点加入\(B\) 然后对所有入边只来自\(B\)的点加入\(C\ ...

  5. Admixture的监督分群(Supervised analysis)

    目录 说明 实战 说明 Admixture通过EM算法一般用于指定亚群分类:或者在不知材料群体结构背景下,通过迭代交叉验证获得error值,取最小error对应的K值为推荐亚群数目.如果我们预先已知群 ...

  6. python-django 模板的抽象和继承

    {% include %}只需要一句即可,不需要end***

  7. python11文件读写模块

    将文件的打开和关闭,交给上下文管理工具with去实现. def read_file(): """ 读取文件 :return: """ fil ...

  8. echo 输出彩色字符

    借助echo的-e选项来实现,语法格式为 echo -e "\033[3xmsome things you want to print out.\033[0m" \033[3xm为 ...

  9. 爬虫动态渲染页面爬取之selenium驱动chrome浏览器的使用

    Selenium是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,可以用其进行网页动态渲染页面的爬取. 支持的浏览器包括IE(7, 8, 9, 10 ...

  10. c#表中信息点击跳转

    OnRowCommand="gridInfoData_RowCommand" <Columns> <asp:ButtonField HeaderText=&quo ...