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.2  PathClassLoader  

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

1.3  代码

       

     package com.example.dynamicloaddemo.jar;       public class DynamicTest implements IDynamic {           @Override       public String helloWorld() {        return "Hello World Form JAR";       }       }

   将这个类导出,注意,编译的时候必须是 java 1.6 编译(java 1.7 编译会出现错误:Zip is good, but no classes.dex inside, and no valid .odex file in the same directory)


1.4  编译文件之后将上面的类打包为 dynamic.jar 

        1.4.1  下载jar 转化 dex 工具,将打包好的jar拷贝到SDK安装目录android-sdk-windows\platform-tools下,DOS进入这个目录,执行命名: dx --dex --output=test.jar dynamic.jar

        1.4.2  将test.jar拷贝到 /data/data/packagename/app-libs/ 

放在 SDCard 上会出现错误   Optimized data directory /data/data/com.example.dynamicloaddemo/files/test.jar is not owned by the current user.  Shared storage cannot protect your application from code injection attacks.


关于Android 动态加载 jar 文件_第1张图片

程序代码:


public class MainActivity extends Activity {

Button mToastButton;


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);


setContentView(R.layout.activity_main);


mToastButton = (Button) findViewById(R.id.main_btn);


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

// }


System.out.println(getDir("libs", Context.MODE_PRIVATE));

System.out.println(getFilesDir());

System.out.println(getCacheDir());

System.out.println(getDir("libs", Context.MODE_PRIVATE));

System.out.println(getDir("libs", Context.MODE_PRIVATE));

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(getDir("libs", Context.MODE_PRIVATE) + 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());

*/

DexClassLoader cl = new DexClassLoader(optimizedDexOutputPath.getAbsolutePath(), getDir("libs", Context.MODE_PRIVATE).getAbsolutePath(), 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.example.dynamicloaddemo.jar.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();

}

}

});


}


}


1.5  运行,出现 Hello World From JAR , 表明动态加载成功。


 


更多相关文章

  1. 【Android】动态链接库so的加载原理
  2. Android内核开发:系统分区与镜像文件的烧写
  3. android动态加载(二)
  4. Android系统编译―Android.mk文件的简单介绍
  5. android 工程中重新生成gen文件夹或R.java 文件
  6. 混合开发:Android的WebView加载H5,和H5的互调|SquirrelNote
  7. [转载]Android布局文件中命名空间的解析
  8. 【动态加载】Android动态加载:简单加载模式
  9. Android Layout布局文件里的android:layout_height等属性不起作

随机推荐

  1. sql server删除前1000行数据的方法实例
  2. Blazor Server 应用程序中进行 HTTP 请求
  3. MySQL令人大跌眼镜的隐式转换
  4. SQL写法--行行比较
  5. Filestream使用简单步骤总结
  6. mybatis动态sql实现逻辑代码详解
  7. 关系型数据库与非关系型数据库简介
  8. mybatis动态sql常用场景总结
  9. SQL Server代理:理解SQL代理错误日志处理
  10. Superset实现动态SQL查询功能