安卓里边可以用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. 使用bootstrap-table时导出excel开头的0被自动省略

    原因是excel"智能"识别数据格式,有时聪明反被聪明误. 解决方案:修改tableExport.js 搜索: if (typeof tdcss != 'undefined' &a ...

  2. 洛谷 P6788 - 「EZEC-3」四月樱花(整除分块)

    题面传送门 题意: 求 \[\prod\limits_{x=1}^n\prod\limits_{y|x}\frac{y^{d(y)}}{\prod\limits_{z|y}z+1} \pmod{p} ...

  3. R之dplyr::select/mutate函数扩展

    select函数 dplyr包select函数用的很多,不过我们一般也是通过正反选列名或数字来选择列. 常见用法如: select(iris,c(1,3)) select(iris,1,3) #同上 ...

  4. Mysql优化,ICP、BNL算法、BKA算法、MMR算法

    ICP(Index Condition Pushdown,索引条件下推)是MySQL5.6版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. 出现原因:ICP出现Mysql5.6以前, ...

  5. python10-高阶函数

    def use_filer(l): """ 获取指定列表/元组中的奇数 :param l: lsit/tuple :return: """ ...

  6. Python查找最长回文暴力方法

    查找最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 例如1: 输入: "babad" 输出: "bab" ...

  7. 微信小程序调试bug-日程计划类

    首先嘤嘤嘤一下,破bug,改了我一天,摔(′д` )-彡-彡 写的个微信小程序 逻辑如下,正常的功能是,我可以新建,修改,查询(按筛选条件),删除某个日程信息,后面贴个页面,我的bug出现就很搞笑了, ...

  8. 大厂高频面试题Spring Bean生命周期最详解

    Spring作为当前Java最流行.最强大的轻量级框架.Spring Bean的生命周期也是面试高频题,了解Spring Bean周期也能更好地帮助我们解决日常开发中的问题.程序员应该都知道Sprin ...

  9. How To Call An Ambulance

    How to Talk to the Emergency Dispatcher [minutesmatter.upmc稻糠亩] How To Call An Ambulance [askambulan ...

  10. E面波导和H面波导的问题

    我感觉与窄壁平行是E面,反之为H面.通常E面(窄面)是指与电场方向平行的方向图切面(窄面):H面(宽面)是指与磁场方向平行的方向图切面(宽面).E面的意思是... ElevationH面的意思是... ...