Android动态加载jar/dex
前言
在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。
声明
欢迎转载,但请保留文章原始出处:)
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.comAndroid中文翻译组: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 执行结果
四、参考文章
五、补充
大家可以看看DexClassLoader的API文档,里面不提倡从SD卡加载,不安全。此外,我也正在组织翻译组尽快把这个命名空间下的几个类都翻译出来,以供大家参考。
工程下载:这里,Dex文件下载:这里。大家可以直接把Dex文件拷贝到SD卡,然后运行例子。
六、后期维护
6.1 2011-12-1 修复本文错误
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),如果如下命令:
6.2 2012-3-29 本文升级版:
Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类
请大家参照最新的文章来做动态加载!
相关推荐
在Android应用开发中,动态加载jar或dex文件是一种常见的优化技术,它允许应用程序在运行时加载新的代码或库,而不必通过更新整个apk来实现功能的扩展或修复。这种技术通常用于热修复、插件化或者模块化开发,能够极...
在Android开发中,动态加载JAR(Java Archive)文件是一种常见的技术,它允许应用程序在运行时加载和执行不在原始APK文件中的代码。这种技术有多种应用场景,例如更新功能、热修复、插件化框架等。下面将详细介绍...
在Android开发中,打包JAR和DEX文件是两个重要的步骤,它们涉及到应用的构建和运行。JAR(Java Archive)是Java平台上的一个文件格式,用于集合多个类文件和其他资源,便于分发和使用。而DEX(Dalvik Executable)是...
在Android开发中,有时我们需要实现动态加载功能,例如在运行时添加或更新功能模块,而无需重新编译和发布整个应用程序。这就是动态加载jar文件的作用。动态加载不仅可以提高应用程序的灵活性,还可以降低更新成本,...
- **动态加载**:部分功能动态加载,不在APK中直接包含,使得反编译者难以获取完整代码。 - **签名验证**:应用签名可以防止篡改,确保代码完整性。 了解并掌握反编译工具如dex2jar的使用,对于开发者来说,不仅...
综上所述,Android动态加载jar代码是通过转换.dex文件并利用DexClassLoader实现的。这一技术为应用带来了更大的灵活性,但同时也需要注意性能和兼容性问题。在实际开发中,根据项目需求和场景选择合适的加载策略至关...
《dex2jar-2.0:深入理解Android APK反编译技术》 在移动应用开发领域,Android系统以其开源、灵活的特点受到了广大开发者们的青睐。然而,为了保护应用程序的源代码不被轻易获取,开发者通常会将Java源代码编译成...
本资料“安卓插件机制相关-android动态加载插件dex后的jar以方便功能扩展.rar”似乎提供了实现这一目标的一些代码示例。 首先,我们需要理解Android插件机制的核心概念。Android插件系统通常基于类加载器...
在Android应用开发中,dex(Dalvik Executable)文件和jar(Java Archive)文件是两种重要的格式,它们分别用于不同的平台和目的。本工具提供了一种便捷的方式,通过简单的拖放操作,实现在dex和jar之间的相互转换。...
总结一下,DexClassLoader在Android开发中扮演着动态加载额外类库的角色,特别是在处理Assets目录下的.dex和.jar文件时。通过正确配置和使用,我们可以灵活地扩展应用的功能,同时避免方法数过多的问题。在实践中,...
因此,在 Android 应用中直接动态加载 .jar 文件是不可行的,必须先将 .jar 文件转换为 .dex 文件格式。 **1.2 可用于动态加载的 API** 1. **DexClassLoader**:可以用来动态加载 .jar、.apk 或者 .dex 文件,甚至...
这个"APK反编译工具包(dex/jar/xml)"提供了一套完整的工具链,帮助开发者将APK中的关键组件解析出来,便于分析和修改。 首先,我们来看第一个工具“dex2jar”。在Android系统中,Java代码经过Dalvik虚拟机的优化...
在Android平台上,动态加载.jar文件是一项关键的技术,它允许应用程序在运行时加载新的功能或更新代码,无需重新安装整个应用。下面将详细讲解这一过程的实现步骤和涉及到的知识点。 首先,我们需要创建.jar文件。...
dex2jar是一个开源的工具,由Pangolin项目开发,它的主要功能是将Android应用中的.dex文件(Dalvik Executable)转换为Java类库的.jar文件。通过这个转换过程,开发者可以使用常规的Java反编译工具(如JD-GUI或JAD)...
### Android中动态加载jar包详解 #### 一、概述 在Android开发中,有时需要实现动态加载外部的jar包或类文件。这种技术可以提高应用的灵活性和扩展性,允许开发者在不重新编译和发布整个应用的情况下更新部分功能...
在Android应用开发中,Dalvik Executable (DEX) 文件是Android系统用来运行应用程序的格式,而Java类库通常是以Java Archive (JAR) 文件的形式存在。`jar转dex工具`就是为了将Java的JAR文件转换为Android兼容的DEX...
4. 运行JD-GUI,加载由dex2jar生成的.jar文件,查看反编译出的Java源代码。 5. 如果需要更深入地理解代码,可以在Apktool解包后的.smali文件中寻找对应的汇编代码,虽然这比阅读Java源代码更为复杂,但有时是必要的...
在逆向工程中,这些工具通常与其他反编译器(如Apktool、dex2jar和JD-GUI)结合使用,以帮助开发者解包APK,查看源代码,甚至修改代码并重新打包。通过这种手段,开发者可以检查代码逻辑,查找潜在的安全漏洞,或者...
运行JD-GUI,然后加载`classes_dex2jar.jar`,你就能看到类和方法的Java源代码了。 4. **注意事项**:尽管dex2jar能提供源代码级别的理解,但反编译的结果可能并不完全等同于原始的Java源代码,因为编译过程中会...
标题 "dex2jar_2.0" 涉及到的是Android应用开发中的一个重要工具,它主要用于将Android应用的Dalvik Executable (DEX) 文件转换为Java类库的Java Archive (JAR) 文件。这个过程被称为反编译,因为DEX文件是Android...