您的位置:首页 > 移动开发 > Android开发

Android动态加载jar/dex

2012-08-27 14:50 295 查看
[align=left]前言[/align]
[align=left]   在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势。本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病。[/align]
正文
  一、 基本概念和注意点

[align=left]    1.1  首先需要了解一点:在Android中可以动态加载,但无法像Java中那样方便动态加载jar[/align]
      原因:Android的虚拟机(Dalvik VM)是不认识Java打出jar的byte code,需要通过dx工具来优化转换成Dalvik byte code才行。这一点在咱们Android项目打包的apk中可以看出:引入其他Jar的内容都被打包进了classes.dex。

[align=left]      所以这条路不通,请大家注意。[/align]

[align=left]    1.2  当前哪些API可用于动态加载[/align]
[align=left]      1.2.1  DexClassLoader[/align]
[align=left]        这个可以加载jar/apk/dex,也可以从SD卡中加载,也是本文的重点。[/align]
[align=left]      1.2.3  PathClassLoader  [/align]
[align=left]        只能加载已经安装到Android系统中的apk文件。[/align]

  二、 准备

[align=left]    本文主要参考"四、参考文章"中第一篇文章,补充细节和实践过程。[/align]
[align=left]    2.1  下载开源项目[/align]
[align=left]      http://code.google.com/p/goodev-demo[/align]
[align=left]      将项目导入工程,工程报错的话应该是少了gen文件夹,手动添加即可。注意这个例子是从网上下载优化好的jar(已经优化成dex然后再打包成的jar)到本地文件系统,然后再从本地文件系统加载并调用的。本文则直接改成从SD卡加载。[/align]

  三、实践

[align=left]    3.1  编写接口和实现[/align]
[align=left]      注意,直接在这个开源项目里面编写以下代码![/align]
[align=left]      3.1.1  接口IDynamic[/align]

package com.dynamic;

public interface IDynamic {

public String helloWorld();

}

复制代码

[align=left]3.1.2  实现类DynamicTest[/align]

package com.dynamic;

public class DynamicTest implements IDynamic {

@Override

public String helloWorld() {

return "Hello World!";

}

}

复制代码

[align=left]3.2  打包并转成dex[/align]
[align=left]      3.2.1  选中工程,常规流程导出即可,如图:[/align]



2011-11-28 22:15 上传
下载附件
(83.87 KB)

[align=left]注意:在实践中发现,自己新建一个Java工程然后导出jar是无法使用的,这一点大家可以根据文章一来了解相关原因,也是本文的重点之一。这里打包导出为dynamic.jar[/align]
[align=left]      3.2.2  将打包好的jar拷贝到SDK安装目录android-sdk-windows\platform-tools下,DOS进入这个目录,执行命名:[/align]

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

复制代码

[align=left]3.3  修改调用例子[/align]
[align=left]      修改MainActivity,如下:[/align]

@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 + "dynamic.dex");

// 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();

}

}

});

}

复制代码

[align=left]3.4  执行结果[/align]

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: