`

Android动态加载jar/dex

 
阅读更多

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  修复本文错误

      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中的类

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

分享到:
评论

相关推荐

    Android动态加载jar/dex,基于android studio+android开发艺术其他demo

    在Android应用开发中,动态加载jar或dex文件是一种常见的优化技术,它允许应用程序在运行时加载新的代码或库,而不必通过更新整个apk来实现功能的扩展或修复。这种技术通常用于热修复、插件化或者模块化开发,能够极...

    android动态加载jar

    在Android开发中,动态加载JAR(Java Archive)文件是一种常见的技术,它允许应用程序在运行时加载和执行不在原始APK文件中的代码。这种技术有多种应用场景,例如更新功能、热修复、插件化框架等。下面将详细介绍...

    android打包JAR,DEX

    在Android开发中,打包JAR和DEX文件是两个重要的步骤,它们涉及到应用的构建和运行。JAR(Java Archive)是Java平台上的一个文件格式,用于集合多个类文件和其他资源,便于分发和使用。而DEX(Dalvik Executable)是...

    android动态加载jar文件

    在Android开发中,有时我们需要实现动态加载功能,例如在运行时添加或更新功能模块,而无需重新编译和发布整个应用程序。这就是动态加载jar文件的作用。动态加载不仅可以提高应用程序的灵活性,还可以降低更新成本,...

    Android反编译工具dex2jar

    - **动态加载**:部分功能动态加载,不在APK中直接包含,使得反编译者难以获取完整代码。 - **签名验证**:应用签名可以防止篡改,确保代码完整性。 了解并掌握反编译工具如dex2jar的使用,对于开发者来说,不仅...

    android 动态加载jar代码

    综上所述,Android动态加载jar代码是通过转换.dex文件并利用DexClassLoader实现的。这一技术为应用带来了更大的灵活性,但同时也需要注意性能和兼容性问题。在实际开发中,根据项目需求和场景选择合适的加载策略至关...

    dex2jar-2.0

    《dex2jar-2.0:深入理解Android APK反编译技术》 在移动应用开发领域,Android系统以其开源、灵活的特点受到了广大开发者们的青睐。然而,为了保护应用程序的源代码不被轻易获取,开发者通常会将Java源代码编译成...

    安卓插件机制相关-android动态加载插件dex后的jar以方便功能扩展.rar

    本资料“安卓插件机制相关-android动态加载插件dex后的jar以方便功能扩展.rar”似乎提供了实现这一目标的一些代码示例。 首先,我们需要理解Android插件机制的核心概念。Android插件系统通常基于类加载器...

    dex与jar相互转换工具

    在Android应用开发中,dex(Dalvik Executable)文件和jar(Java Archive)文件是两种重要的格式,它们分别用于不同的平台和目的。本工具提供了一种便捷的方式,通过简单的拖放操作,实现在dex和jar之间的相互转换。...

    DexClassLoader自定义加载Assets目录下的dex、jar文件

    总结一下,DexClassLoader在Android开发中扮演着动态加载额外类库的角色,特别是在处理Assets目录下的.dex和.jar文件时。通过正确配置和使用,我们可以灵活地扩展应用的功能,同时避免方法数过多的问题。在实践中,...

    动态加载apk或者jar或者dex.docx

    因此,在 Android 应用中直接动态加载 .jar 文件是不可行的,必须先将 .jar 文件转换为 .dex 文件格式。 **1.2 可用于动态加载的 API** 1. **DexClassLoader**:可以用来动态加载 .jar、.apk 或者 .dex 文件,甚至...

    APK反编译工具包(dex/jar/xml )

    这个"APK反编译工具包(dex/jar/xml)"提供了一套完整的工具链,帮助开发者将APK中的关键组件解析出来,便于分析和修改。 首先,我们来看第一个工具“dex2jar”。在Android系统中,Java代码经过Dalvik虚拟机的优化...

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

    在Android平台上,动态加载.jar文件是一项关键的技术,它允许应用程序在运行时加载新的功能或更新代码,无需重新安装整个应用。下面将详细讲解这一过程的实现步骤和涉及到的知识点。 首先,我们需要创建.jar文件。...

    Android反编译器(dex2jar)

    dex2jar是一个开源的工具,由Pangolin项目开发,它的主要功能是将Android应用中的.dex文件(Dalvik Executable)转换为Java类库的.jar文件。通过这个转换过程,开发者可以使用常规的Java反编译工具(如JD-GUI或JAD)...

    Android中动态加载jar包

    ### Android中动态加载jar包详解 #### 一、概述 在Android开发中,有时需要实现动态加载外部的jar包或类文件。这种技术可以提高应用的灵活性和扩展性,允许开发者在不重新编译和发布整个应用的情况下更新部分功能...

    jar转dex工具.rar

    在Android应用开发中,Dalvik Executable (DEX) 文件是Android系统用来运行应用程序的格式,而Java类库通常是以Java Archive (JAR) 文件的形式存在。`jar转dex工具`就是为了将Java的JAR文件转换为Android兼容的DEX...

    Android app反编译工具(dex2jar-2.0.zip apktool_2.4.1.jar jd-gui-1.6.6.jar)

    4. 运行JD-GUI,加载由dex2jar生成的.jar文件,查看反编译出的Java源代码。 5. 如果需要更深入地理解代码,可以在Apktool解包后的.smali文件中寻找对应的汇编代码,虽然这比阅读Java源代码更为复杂,但有时是必要的...

    android 反编译 逆向 vdex2dex odex2dex

    在逆向工程中,这些工具通常与其他反编译器(如Apktool、dex2jar和JD-GUI)结合使用,以帮助开发者解包APK,查看源代码,甚至修改代码并重新打包。通过这种手段,开发者可以检查代码逻辑,查找潜在的安全漏洞,或者...

    dex2jar反编译dex文件

    运行JD-GUI,然后加载`classes_dex2jar.jar`,你就能看到类和方法的Java源代码了。 4. **注意事项**:尽管dex2jar能提供源代码级别的理解,但反编译的结果可能并不完全等同于原始的Java源代码,因为编译过程中会...

    dex2jar_2.0

    标题 "dex2jar_2.0" 涉及到的是Android应用开发中的一个重要工具,它主要用于将Android应用的Dalvik Executable (DEX) 文件转换为Java类库的Java Archive (JAR) 文件。这个过程被称为反编译,因为DEX文件是Android...

Global site tag (gtag.js) - Google Analytics