Android动态加载jar/dex

转载 2012年08月27日 14:50:15
前言
   在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。
正文
  一、 基本概念和注意点
    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
  1. package com.dynamic;

  2. public interface IDynamic {
  3.     public String helloWorld();
  4. }
复制代码

3.1.2  实现类DynamicTest
  1. package com.dynamic;

  2. public class DynamicTest implements IDynamic {

  3.     @Override
  4.     public String helloWorld() {
  5.         return "Hello World!";
  6.     }
  7. }
复制代码

3.2  打包并转成dex
      3.2.1  选中工程,常规流程导出即可,如图:
8.jpg
2011-11-28 22:15 上传
下载附件 (83.87 KB)
注意:在实践中发现,自己新建一个Java工程然后导出jar是无法使用的,这一点大家可以根据文章一来了解相关原因,也是本文的重点之一。这里打包导出为dynamic.jar
      3.2.2  将打包好的jar拷贝到SDK安装目录android-sdk-windows\platform-tools下,DOS进入这个目录,执行命名:
  1. dx --dex --output=dynamic.dex dynamic.jar
复制代码

3.3  修改调用例子
      修改MainActivity,如下:
  1. @Override
  2.     public void onCreate(Bundle savedInstanceState) {
  3.         super.onCreate(savedInstanceState);
  4.         setContentView(R.layout.main);
  5.         mToastButton = (Button) findViewById(R.id.toast_button);
  6.        
  7.         // Before the secondary dex file can be processed by the DexClassLoader,
  8.         // it has to be first copied from asset resource to a storage location.
  9. //        final File dexInternalStoragePath = new File(getDir("dex", Context.MODE_PRIVATE),SECONDARY_DEX_NAME);
  10. //        if (!dexInternalStoragePath.exists()) {
  11. //            mProgressDialog = ProgressDialog.show(this,
  12. //                    getResources().getString(R.string.diag_title),
  13. //                    getResources().getString(R.string.diag_message), true, false);
  14. //            // Perform the file copying in an AsyncTask.
  15. //            // 从网络下载需要的dex文件
  16. //            (new PrepareDexTask()).execute(dexInternalStoragePath);
  17. //        } else {
  18. //            mToastButton.setEnabled(true);
  19. //        }
  20.        
  21.         mToastButton.setOnClickListener(new View.OnClickListener() {
  22.             public void onClick(View view) {
  23.                 // Internal storage where the DexClassLoader writes the optimized dex file to.
  24.                 //final File optimizedDexOutputPath = getDir("outdex", Context.MODE_PRIVATE);
  25.                 final File optimizedDexOutputPath = new File(Environment.getExternalStorageDirectory().toString()
  26.                     + File.separator + "dynamic.dex");
  27.                 // Initialize the class loader with the secondary dex file.
  28. //                DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
  29. //                        optimizedDexOutputPath.getAbsolutePath(),
  30. //                        null,
  31. //                        getClassLoader());
  32.                 DexClassLoader cl = new DexClassLoader(optimizedDexOutputPath.getAbsolutePath(),
  33.                     Environment.getExternalStorageDirectory().toString(), null, getClassLoader());
  34.                 Class libProviderClazz = null;
  35.                
  36.                 try {
  37.                     // Load the library class from the class loader.
  38.                     // 载入从网络上下载的类
  39. //                    libProviderClazz = cl.loadClass("com.example.dex.lib.LibraryProvider");
  40.                     libProviderClazz = cl.loadClass("com.dynamic.DynamicTest");
  41.                    
  42.                     // Cast the return object to the library interface so that the
  43.                     // caller can directly invoke methods in the interface.
  44.                     // Alternatively, the caller can invoke methods through reflection,
  45.                     // which is more verbose and slow.
  46.                     //LibraryInterface lib = (LibraryInterface) libProviderClazz.newInstance();
  47.                     IDynamic lib = (IDynamic)libProviderClazz.newInstance();
  48.                    
  49.                     // Display the toast!
  50.                     //lib.showAwesomeToast(view.getContext(), "hello 世界!");
  51.                     Toast.makeText(MainActivity.this, lib.helloWorld(), Toast.LENGTH_SHORT).show();
  52.                 } catch (Exception exception) {
  53.                     // Handle exception gracefully here.
  54.                     exception.printStackTrace();
  55.                 }
  56.             }
  57.         });
  58.     }
复制代码

3.4  执行结果
9.png

Android插件化开发之DexClassLoader动态加载dex、jar小Demo

一、温故动态加载ClassLoader机制 如果对Android的ClassLoader加载机制不熟悉,猛戳Android插件化开发动态加载基础之ClassLoader工作机制 http://blog...
  • u011068702
  • u011068702
  • 2016年11月21日 20:55
  • 5470

Android动态加载jar,dex,apk文件

最近发现Android有一个发展方向,插件化,像360等等,他把功能索引放在主界面,当使用哪个功能就调用哪个jar,dex,或者apk,这种技术叫做动态加载,那么我们来看看这个dex实现了什么功能 ...
  • salute_li
  • salute_li
  • 2016年07月23日 20:55
  • 1474

Android动态加载jar/dex

Android动态加载jar/dex 前言    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,...
  • bboyfeiyu
  • bboyfeiyu
  • 2013年09月12日 10:35
  • 1878

Android动态加载dex技术初探

今天不忙,研究了下Android动态加载dex的技术,主要参考:            1、http://www.cnblogs.com/over140/archive/2011/11/23/2259...
  • u013478336
  • u013478336
  • 2016年02月25日 00:19
  • 12078

Android动态加载Dex机制解析

什么是类加载器?    类加载器(class loader)是 Java™中的一个很重要的概念。类加载器负责加载 Java 类的字节代码到 Java 虚拟机中。 Java 虚拟机使用 Java 类的方...
  • wy353208214
  • wy353208214
  • 2016年04月12日 12:45
  • 10987

动态加载Dex的原理

1 问题 在Android系统中,一个App的所有代码都在一个Dex文件里面。Dex是一个类似Jar的存 储了多有Java编译字节码的归档文件。因为Android系统使用Dalvik虚拟机,所以...
  • dxddxd1987
  • dxddxd1987
  • 2016年06月06日 20:37
  • 654

Android插件化(二):使用DexClassLoader动态加载assets中的apk

Android插件化(二):使用DexClassLoader动态加载assets中的apk简介上一篇博客讲到,我们可以使用MultiDex.java加载离线的apk文件。需要注意的是,apk中的类是加...
  • NUPTboyZHB
  • NUPTboyZHB
  • 2015年12月27日 20:47
  • 4345

android jar文件与dex文件的转换

一、dex文件转为jar文件 1.第一篇 Android 反编译资料整理 Made by 李文栋  rayleeya@gmail.com 2010-12-13  Monday 于北京 ...
  • shfscut
  • shfscut
  • 2017年05月09日 11:33
  • 448

android APK加固篇-2.动态加载dex及dex的方法的调用

1.用于动态加载的dex可以放在sdcard中进行加载,但是为了安全起见还是觉得放在asset中, 加载之前把dex复制到app的data空间中更好。 String copyDex(String d...
  • csdn49532
  • csdn49532
  • 2016年02月02日 11:02
  • 1775

利用DexClassLoader动态加载dex文件

Java中也有类加载器ClassLoader,其作用是动态装载Class文件,当我们从网络下载Class文件,或者在编译时不参与而在运行时动态调用时就需要用类加载器。由于Android对class文件...
  • cauchyweierstrass
  • cauchyweierstrass
  • 2016年04月05日 15:50
  • 1673
收藏助手
不良信息举报
您举报文章:Android动态加载jar/dex
举报原因:
原因补充:

(最多只允许输入30个字)