Android动态加载dex文件/jar包的纯原生代码实现(dex文件由服务端下发)

介绍原理的文章有很多,我就不再多说,直奔主题:

一、生成dex文件(源码下载地址:https://download.csdn.net/download/wanggangyanqing/18658862

1.新建module实现需要动态加载的模块,我以简单的获取UUID为例:

class DexTest {
    public String getUUID() {
        String uuid = UUID.randomUUID().toString(); //获取UUID并转化为String对象
        uuid = uuid.replace("-", "");               //因为UUID本身为32位只是生成时多了“-”,所以将它们去点就可
        Log.e("DEX", "uuid" + uuid);
        return uuid;
    }
}

2.打包含dex文件的jar包

①在module的build中添加:

task againMakeJar(type: Copy) {
    delete 'libs/dextest.jar' //删除之前的旧jar包
    from('build/intermediates/aar_main_jar/release/') //从这个目录下取出默认jar包
    into('libs/') //将jar包输出到指定目录下
    include('classes.jar')
    exclude('text/', 'BuildConfig.class', 'R.class')//去掉不需要打包的目录和文件
    exclude { it.name.startsWith('R$') }//去掉R$开头的文件
    rename('classes.jar', 'dextest.jar') //自定义jar包的名字
}

②双击gradle中againMackJar即可编译生成jar包:

3,将jar包转dex文件:

①将生成的jar包复制到SDK\build-tools\30.0.3中,cmd打开terminal执行dx命令:dx --dex --output=newdextest.jar dextest.jar,执行完生成newdextest.jar包。

②将newdextest.jar改成newdextest.zip并解压,得到的classes.dex文件即是我们需要的dex文件。

二、下载并执行dex文件(源码地址:https://download.csdn.net/download/wanggangyanqing/18658926

1.从服务端下载dex文件并将其保存到App私有目录(我的dex下载路径:http://chuanglan-test.oss-cn-shanghai.aliyuncs.com/sdk/platform/sms_sdk/classes.dex

String saveFilePath = null;//dex保存路径
File appPath = getFilesDir(); //获取app私有目录
saveFilePath = appPath + "dextest.dex"; 
String dexDownLoadUrl = "http://chuanglan-test.oss-cn-shanghai.aliyuncs.com/sdk/platform/sms_sdk/classes.dex";//下载链接
URL url = new URL(dexDownLoadUrl);//创建一个URL对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();//创建HttpURLConnection对象
conn.setConnectTimeout(10000);//设置连接超时
conn.setReadTimeout(10000);//设置读超时
conn.setRequestMethod("GET");//设置GET请求方式
int responseCode = conn.getResponseCode();//服务端响应码
if (responseCode == 200) {
byte[] bytes = new byte[1024];
int len = -1;
InputStream in = conn.getInputStream();//得到InputStream
//创建一个文件输出流,用指定的名字创建文件
FileOutputStream out = new FileOutputStream(saveFilePath, false);
//从InputStream当中读取数据,并写入
 while ((len = in.read(bytes)) != -1) {
    out.write(bytes, 0, len);
    out.flush();
      }
    out.close();
    in.close();
        }

2.通过反射加载dex文件

    private void loadDex(String saveFilePath) throws ClassNotFoundException {
        DexClassLoader dexClassLoader = new DexClassLoader(saveFilePath, saveFilePath, null, getClassLoader());
        Class<?> clz = dexClassLoader.loadClass("com.test.dexlib.DexTest");
        Object instanceObject = getDecInstanceObject(clz);
        Method method = getDecMethod(clz, "getUUID", null);
        String uuid = invoke(method, instanceObject, null);
        Log.e("DEX", "dex文件执行结果  UUID=" + uuid);
    }
    public static Object getDecInstanceObject(Class<?> aClass) {
        Object instance = null;
        if (null != aClass) {
            try {
                Constructor constructor = aClass.getDeclaredConstructor();
                //打开禁用访问控制检查
                constructor.setAccessible(true);
                instance = constructor.newInstance();
            } catch (Exception e) {
                Log.e("DEX", "getDecInstanceObject  e=" + e);
            }
        }
        return instance;
    }
    public static Method getDecMethod(Class<?> aClass, String aMethod, Class<?>[] classType) {
        Method method = null;
        if (aClass != null) {
            try {
                method = aClass.getDeclaredMethod(aMethod, classType);
                method.setAccessible(true);
            } catch (Exception e) {
                Log.e("DEX", "getDecMethod  e=" + e);
            }
        }
        return method;
    }
    public static String invoke(Method method, Object instanceObject, Object[] params) {
        String result = null;
        try {
            if (method != null && instanceObject != null) {
                result = (String) method.invoke(instanceObject, params);
            }
        } catch (Exception e) {
            Log.e("DEX", "invoke  e=" + e);
        }
        return result;
    }

至此,生成dex文件并从服务端下载,然后在App中动态加载已下载的dex文件完整流程已经结束。

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值