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.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.
程序代码:
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 , 表明动态加载成功。
看完上述内容,你们掌握Android 中怎么动态加载 jar 文件的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。