標籤:android package public java 虛擬機器
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.
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/5B/84/wKiom1UKkMrQb82RAACcD1kPgqo464.jpg" title="QQ20150319170138.png" alt="wKiom1UKkMrQb82RAACcD1kPgqo464.jpg" />
程式碼:
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 , 表明動態載入成功。
本文出自 “Lua學習筆記” 部落格,請務必保留此出處http://mythwind.blog.51cto.com/6506705/1622297
關於Android 動態載入 jar 檔案