android 基于dex的插件化开发
安卓里边可以用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的插件化开发的更多相关文章
- Android基于代理的插件化思路分析
前言 正常的App开发流程基本上是这样的:开发功能-->测试--->上线,上线后发现有大bug,紧急修复---->发新版本---->用户更新----->bug修复.从发现 ...
- JavaScript插件化开发
大熊君JavaScript插件化开发 一,开篇分析 Hi,大家好!大熊君又和大家见面了,还记得昨天的那篇文章吗------这个系列的开篇(第一季).主要讲述了以“jQuery的方式如何开发插件”, 那 ...
- Android 插件化开发(二):加载外部Dex文件
在学习Java反射的技术后,我们可以开始更深一步的探究插件化开发了.首先先讲一下Android App的打包流程,然后我们通过一个简单的例子 —— 实现插件化加载外部Dex来完成初级的插件化开发的探索 ...
- Android插件化开发
客户端开发给人的印象往往是小巧,快速奔跑.但随着产品的发展,目前产生了大量的门户型客户端.功能模块持续集成,开发人员迅速增长.不同的开发小组开发不同的功能模块,甚至还有其他客户端集成进入.能做到功能模 ...
- 《Android插件化开发指南》面世
本书在京东购买地址:https://item.jd.com/31178047689.html 本书Q群:389329264 (一)这是一本什么书 如果只把本书当作纯粹介绍Android插件化技术的书籍 ...
- Android插件化开发---执行未安装apk中的Service
欢迎各位增加我的Android开发群[257053751] 假设你还不知道什么叫插件化开发.那么你应该先读一读之前写的这篇博客:Android插件化开发,初入殿堂 上一篇博客主要从总体角度分析了一下 ...
- 【我的Android进阶之旅】Android插件化开发学习资料
1.目前开源的插件开发框架大致有哪些? 1. 任玉刚 的 dynamic-load-apk Github 地址:https://github.com/singwhatiwanna/dynamic-lo ...
- 详解Android插件化开发-资源访问
动态加载技术(也叫插件化技术),当项目越来越庞大的时候,我们通过插件化开发不仅可以减轻应用的内存和CPU占用,还可以实现热插拔,即在不发布新版本的情况下更新某些模块. 通常我们把安卓资源文件制 ...
- Android 插件化开发(四):插件化实现方案
在经过上面铺垫后,我们可以尝试整体实现一下插件化了.这里我们先介绍一下最简单的实现插件化的方案. 一.最简单的插件化实现方案 最简单的插件化实现方案,对四大组件都是适用的,技术面涉及如下: 1). 合 ...
随机推荐
- [loj6518]序列
参考ExtremeSpanningTrees,考虑优化整体二分时求$g_{i}\in \{w_{mid},w_{mid+1}\}$的最优解 首先题目有一个条件似乎没有写出来,是保证$l\le k\le ...
- [cf1421E]Swedish Heroes
令$p_{i}$为最终$a_{i}$之前的系数($p_{i}\in \{-1,1\}$),则有$n+\sum_{i=1}^{n}[p_{i}=-1]\equiv 1(mod\ 3)$ 证明:对于两个满 ...
- 论文翻译:2020_A Recursive Network with Dynamic Attention for Monaural Speech Enhancement
论文地址:基于动态注意的递归网络单耳语音增强 论文代码:https://github.com/Andong-Li-speech/DARCN 引用格式:Li, A., Zheng, C., Fan, C ...
- Ubuntu怎么修改DNS
有时候会出现配置好网络之后,可以ping通网关却ping不通www.baidu.com orangepi@orangepi3:~$ ping 192.168.1.1 PING 192.168.1.1 ...
- AGC050B Three Coins
做的时候有思考到是否能转化成移动点问题,但是没有清晰的把他解释出来. NOIP的时候也一样,T3也有考虑到是否能转为差分,但是也没有清晰的写出来. 自己做题的时候应尽量保证草稿纸和思绪的清晰,而不是在 ...
- ABC 210
A 按题意模拟. scanf("%lld%lld%lld%lld",&n,&a,&x,&y); std::cout<<n * x - ( ...
- xshell的快捷复制粘贴设置
今天试着用xshell连接Linux,运行一些命令的时候想快点复制粘贴实现效率,却发现还要右键选择复制,再右键选择粘贴,很是麻烦. 看了一下xshell的设置,其实可以自己设置成快捷方式 以xshel ...
- 同步阻塞IO模型
同步阻塞IO模型 有上篇IO模型中的,同步阻塞IO模型,我们能够知道,用户线程发起请求后就一直阻塞的等待 内核完成准备数据.数据拷贝的工作.并且返回成功的指示. 实现 使用java来实现同步阻塞IO模 ...
- org.apache.hadoop.hive.ql.metadata.HiveException: Internal Error: cannot generate all output rows for a Partition解决
自己在路径访问明细表开发时,写的sql如下 SELECT guid, sessionid, event['url'] as page, `timestamp` as ts, row_number() ...
- openwrt编译ipk包提示缺少feeds.mk文件
问题具体表现如下 这个问题困扰了我两个多星期,总算解决了.解决方案如下: 首先,先应该把配置菜单调好. 我的硬件是7620a,要编译的ipk包为helloworld,所以应该使用 make menuc ...