Android动态加载jar/dex

逆向开发使用dx.jar、d8.jar、baksmali.jar将jar转dex文件,解决requires --min-sdk-version >= 26 (currently 13)问题 逆向开发使用dx.jar、d8.jar、baksmali.jar将jar转dex文件,解决requires --min-sdk-version >= 26 (currently 13)问题 阅读详情

Android动态加载jar/dex


前言

   在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。

 

声明

  欢迎转载,但请保留文章原始出处:) 

    博客园:http://www.cnblogs.com

    农民伯伯: http://over140.cnblogs.com  

    Android中文翻译组:http://androidbox.sinaapp.com/

 

正文

  一、 基本概念和注意点

    1.1  首先需要了解一点:在Android中可以动态加载,但无法像Java中那样方便动态加载jar

      原因:Android的虚拟机(Dalvik VM)是不认识Java打出jar的byte code,需要通过dx工具来优化转换成Dalvik byte code才行。这一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。

      所以这条路不通,请大家注意。

 

    1.2  当前哪些API可用于动态加载

      1.2.1  DexClassLoader

        这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点。

      1.2.3  PathClassLoader  

        只能加载已经安装到Android系统中的apk文件。

 

  二、 准备

    本文主要参考"四、参考文章"中第一篇文章,补充细节和实践过程。

    2.1  下载开源项目

      http://code.google.com/p/goodev-demo

      将项目导入工程,工程报错的话应该是少了gen文件夹,手动添加即可。注意这个例子是从网上下载优化好的jar(已经优化成dex然后再打包成的jar)到本地文件系统,然后再从本地文件系统加载并调用的。本文则直接改成从SD卡加载。

 

  三、实践

    3.1  编写接口和实现

      3.1.1  接口IDynamic

package com.dynamic;

public  interface IDynamic {
     public String helloWorld();
}

       3.1.2  实现类DynamicTest

复制代码
package com.dynamic;

public  class DynamicTest  implements IDynamic {

    @Override
     public String helloWorld() {
         return "Hello World!";
    }
}
复制代码

 

    3.2  打包并转成dex

      3.2.1  选中工程,常规流程导出即可,如图:

      注意:在实践中发现,自己新建一个Java工程然后导出jar是无法使用的,这一点大家可以根据文章一来了解相关原因,也是本文的重点之一。这里打包导出为dynamic.jar

      (后期修复:打包请不要把接口文件打进来,参见文章末尾后续维护!)

      3.2.2  将打包好的jar拷贝到SDK安装目录android-sdk-windows\platform-tools下,DOS进入这个目录,执行命名:

dx --dex --output=test.jar dynamic.jar

 

    3.3  修改调用例子

      修改MainActivity,如下:

复制代码
    @Override
     public  void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mToastButton = (Button) findViewById(R.id.toast_button);
        
         //  Before the secondary dex file can be processed by the DexClassLoader,
        
//  it has to be first copied from asset resource to a storage location.
//         final File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE),SECONDARY_DEX_NAME);
//         if (!dexInternalStoragePath.exists()) {
//             mProgressDialog = ProgressDialog.show(this,
//                     getResources().getString(R.string.diag_title), 
//                     getResources().getString(R.string.diag_message), true, false);
//              //  Perform the file copying in an AsyncTask.
//              //  从网络下载需要的dex文件
//             (new PrepareDexTask()).execute(dexInternalStoragePath);
//         } else {
//             mToastButton.setEnabled(true);
//         }
        
        mToastButton.setOnClickListener( new View.OnClickListener() {
             public  void onClick(View view) {
                 //  Internal storage where the DexClassLoader writes the optimized dex file to.
                
// final File optimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);
                 final File optimizedDexOutputPath =  new File(Environment.getExternalStorageDirectory().toString()
                    + File.separator + "test.jar");
                 //  Initialize the class loader with the secondary dex file.
//                 DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
//                         optimizedDexOutputPath.getAbsolutePath(),
//                         null,
//                         getClassLoader());
                DexClassLoader cl =  new DexClassLoader(optimizedDexOutputPath.getAbsolutePath(),
                    Environment.getExternalStorageDirectory().toString(),  null, getClassLoader());
                Class libProviderClazz =  null;
                
                 try {
                     //  Load the library class from the class loader.
                    
//  载入从网络上下载的类
//                     libProviderClazz = cl.loadClass("com.example.dex.lib.LibraryProvider");
                    libProviderClazz = cl.loadClass("com.dynamic.DynamicTest");
                    
                     //  Cast the return object to the library interface so that the
                    
//  caller can directly invoke methods in the interface.
                    
//  Alternatively, the caller can invoke methods through reflection,
                    
//  which is more verbose and slow.
                    
// LibraryInterface lib = (LibraryInterface) libProviderClazz.newInstance();
                    IDynamic lib = (IDynamic)libProviderClazz.newInstance();
                    
                     //  Display the toast!
                    
// lib.showAwesomeToast(view.getContext(), "hello 世界!");
                    Toast.makeText(MainActivity. this, lib.helloWorld(), Toast.LENGTH_SHORT).show();
                }  catch (Exception exception) {
                     //  Handle exception gracefully here.
                    exception.printStackTrace();
                }
            }
        });
    }
复制代码

 

    3.4  执行结果

     

 

  四、参考文章

    [推荐]在Android中动态载入自定义类

    Android app中加载jar插件

    关于Android的ClassLoader探索

    Android App 如何动态加载类

 

  五、补充

    大家可以看看DexClassLoader的API文档,里面不提倡从SD卡加载,不安全。此外,我也正在组织翻译组尽快把这个命名空间下的几个类都翻译出来,以供大家参考。

    工程下载:这里,Dex文件下载:这里。大家可以直接把Dex文件拷贝到SD卡,然后运行例子。

 

  六、后期维护

    6.1  2011-12-1  修复本文错误

      感谢网友ppp250和liuzhaocn的反馈,基本按照评论2来修改:

      6.1.1  不需要在本工程里面导出jar,自己新建一个Java工程然后导出来也行。

      6.1.2  导出jar时不能带接口文件,否则会报以下错:

         java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation

      6.1.3  将jar优化时应该重新成jar(jar->dex->jar),如果如下命令:

      dx --dex --output=test.jar dynamic.jar

 

    6.2  2012-3-29  本文升级版:

      Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类

      请大家参照最新的文章来做动态加载!

 

dx.jar部分类的用法——以检测https劫持漏洞为例 在ADT的build-tools的目录下,有一个叫做dx.jar的包,这个包可以解析dex文件(目前用到的就是这么多),但是在网上一搜都没看到什么相关接口的资料,只能自己慢慢看(老大给了我很多帮助),算是稍微会了一些相应的接口调用,总结总结,也给需要的朋友一些帮助。 阅读详情

相关推荐

好用的dx.jar 亲测有效

Unable to build: the file dx.jar was not loaded from the SDK folder!

android 动态加载jar包

android 动态加载jar 技术

天燹的博客 2744

安卓dx.jar包

安卓dx开发jar包,安卓启动eclipse报错,提示dx加载错误

Android动态dex下发,Android动态加载jar/dex

前言在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。声明欢迎转载,但请保留文章原始出处:)博客园:http://www.cnblogs.com ...

weixin_42393829的博客 679

Android 中动态加载.jar的实现步骤

首先第一个是 jar 文件的制作,Java 里面直接把 .class 文件打包到 .jar 文件里面就可以了,但是 Android 的 Dalvik VM 是不认 Java 的 byte code 的,所以不能直接这么打包,而要用 dx 工具转成 Dalvik byte code 才可以。当然,dx 工具转了之后,jar 包里面就不 是 .class 文件了,而是 .dex 文件。第二个是,Android 里面虽然也提供了 URLClassLoader 的实现,但是并不能用。要动态加载其它类,可以用的 Class Loader 有: DexClassLoader,PathClassLoader

dx.jar和d8.jar工具

android sdk 的dx.jar和d8.jar工具

android动态加载Jar/dex--原创

背景:开发课题需要对应不同手机,为防止每次更换手机对系统重新开发时间上的浪费。决定把通用的一些功能拿出来,扫描,蓝牙,照相,摄像之类的这些技能,同意开发一个jar动态调用。参考了诸多前辈的网站之后,自己动手写了一下。 相关扫盲: 1. 浅谈Android虚拟机的动态加载技术  2. android动态加载Jar/dex-农民伯伯 3.http://blog.youkuaiyun.com/qq591...

chujingwei的专栏 259

常见信号逻辑电平标准介绍:TTL、CMOS、ECL、LVDS、CML

逻辑电平是指数字信号电压的高、低电平,相关参数定义如下:(1)输入高电平门限Vih:保证逻辑门的输入为高电平时所允许的最小输入高电平,当输入电平高于Vih时,则认为输入电平为高电平;(2)输入低电平门限Vil:保证逻辑门的输入为低电平时所允许的最大输入低电平,当输入电平低于Vil时,则认为输入电平为低电平;(3)输出高电平门限Voh:保证逻辑门的输出为高电平时的输出电平的最小值,逻辑门的输出为高电平时的电平值都必须大于此Voh;

liuchj的博客 1万+

android 动态加载jar/dex文件

最近一直在搞android动态加载这一块内容,感觉还是学会到了很多新的东西,下面就分享给大家。    熟悉java的朋友,肯定知道ClassLoader这个东西,我们可以使用ClassLoader去灵活的加载某个类,但是在android中大家有可能会很陌生;大家都知道,android有自己的虚拟机(Dalvik虚拟机),这和Java的JVM还是有区别的,这里我就不做详细的介绍了,不懂得朋友可以在

qiaobusiwolaile的专栏 1019

Matplotlib图片尺寸调整全攻略:从figsize到savefig的实战技巧

在数据可视化与科学计算中,图形尺寸控制是影响图表可读性与专业度的基础环节。其核心原理在于协调逻辑尺寸(英寸)与物理输出(像素)的映射关系,这直接决定了信息呈现的清晰度与布局合理性。从技术价值看,精准的尺寸控制能提升图表在不同媒介(如学术论文、报告、网页)中的适配性,避免显示不全、模糊失真等常见问题。在应用场景上,无论是Jupyter Notebook中的交互探索、自动化报告的批量生成,还是满足严格出版要求的插图制作,都需要掌握对应的尺寸调整策略。本文聚焦于matplotlib中的figsize参数、rcPa

weixin_30899023的博客 329

宇树GO2-YOLOv5在Jetson Orin上的部署避坑实践

本文详细记录了在宇树GO2四足机器人搭载的Jetson Orin平台上部署YOLOv5目标检测模型的完整实践过程。文章重点分享了从ARM架构认知、网络连接解决方案、Archiconda环境搭建、PyTorch版本精准匹配到依赖安装与性能验证的核心步骤与避坑指南,旨在帮助开发者高效完成边缘计算环境下的算法部署。

app77的博客 669

android 动态切换aar_Android动态加载jar/dex

前言在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。声明欢迎转载,但请保留文章原始出处:)博客园:http://www.cnblogs.com ...

weixin_39628384的博客 1291

百元DIY手机荧光计:低成本荧光检测平台搭建与实战

荧光检测是一种基于物质受特定波长光激发后发射更长波长荧光的分析技术,其核心原理在于光与物质的相互作用。通过选择性激发与检测,该技术能实现对痕量物质的高灵敏度、高特异性定量分析,在生物医学、环境监测和食品安全等领域具有重要价值。传统荧光分光光度计虽精度高,但成本昂贵、体积庞大且操作复杂,限制了其在现场快检和普及教育中的应用。本文聚焦于如何利用智能手机的高性能摄像头和处理器,结合低成本光学滤光片和LED光源,构建一个便携、经济的DIY荧光检测平台。该方案通过简化光路设计,采用带通滤光片进行波长选择,并利用图像处

weixin_34194829的博客 307
上一篇: 从android应用程序跳转到系统的各个设置页面
下一篇: Java数组操作的10大方法
xing...
博客等级 码龄17年 30粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值