androidapk載入
A. android 怎麼動態的載入類
在 java 裡面,我們可以把一些類放到 .jar 文件裡面,然後用 ClassLoader 動態載入。例如:
[java] view plain
URLClassLoader ucl = URLClassLoader.newInstance(new URL[]
{new URL("file:/sdcard/files/test.jar")});
Class clazz = ucl.loadClass("com.test.TestClass");
但是在 Android 上面,情況有所不同。
首先第一個是 jar 文件的製作,Java 裡面直接把 .class 文件打包到 .jar 文件裡面就可以了,但是 Android 的 Dalvik VM 是不認 Java 的 byte code 的,所以不能直接這么打包,而要用 dx 工具轉成 Dalvik byte code 才可以。當然,dx 工具轉了之後,jar 包裡面就不是 .class 文件了,而是 .dex 文件。
第二個是,Android 裡面雖然也提供了 URLClassLoader 的實現,但是並不能用。要動態載入其它類,可以用的 Class Loader 有:
DexClassLoader
PathClassLoader
其中,DexClassLoader 可以載入 apk, jar 或者 dex 文件,例如:
[java] view plain
File jarFile = new File("/sdcard/test.dex");
if ( jarFile.exists() ) {
DexClassLoader cl = new DexClassLoader(jarFile.toString(), "/sdcard/test", null, ClassLoader.getSystemClassLoader());
Class<?> c = cl.loadClass("com.qihoo360.test.Test");
...
}
但是 DexClassLoader 要求指定一個可寫的目錄,即 DexClassLoader 構造函數的第二個參數,在上例中是 /sdcard/test
這個參數的含義是:directory where optimized DEX files should be written
因為 Dalvik 在載入 dex 文件時,會動態進行優化,DexClassLoader 要求指定優化後 dex 文件存放的位置。
PathClassLoader 的限制要更多一些,它只能載入已經安裝到 Android 系統中的 apk 文件,也就是 /data/app 目錄下的 apk 文件。其它位置的文件載入的時候都會出現 ClassNotFoundException. 例如:
[java] view plain
PathClassLoader cl = new PathClassLoader(jarFile.toString(), "/data/app/", ClassLoader.getSystemClassLoader());
為什麼有這個限制呢?我認為這其實是當前 Android 的一個 bug, 因為 PathClassLoader 會去讀取 /data/dalvik-cache 目錄下的經過 Dalvik 優化過的 dex 文件,這個目錄的 dex 文件是在安裝 apk 包的時候由 Dalvik 生成的。例如,如果包的名字是 com.qihoo360.test,Android 應用安裝之後都保存在 /data/app 目錄下,即 /data/app/com.qihoo360.test-1.apk,那麼 /data/dalvik-cache 目錄下就會生成 data@[email protected]@classes.dex 文件。在調用 PathClassLoader 時,它就會按照這個規則去找 dex 文件,如果你指定的 apk 文件是 /sdcard/test.apk,它按照這個規則就會去讀 /data/dalvik-cache/[email protected]@classes.dex 文件,顯然這個文件不會存在,所以 PathClassLoader 會報錯。
在 Google 修正這個問題之前,我們要麼就只能用 DexClassLoader,要麼就只能用 PathClassLoader 載入已安裝的 apk 了。
B. 安卓開發怎麼先啟動APP再載入資源 因為APP啟動太慢了,我想先啟動進入activity,然後
可以開一個線程,把不需要及時顯示的放在線程中載入
C. 如何動態載入android的so文件,如何壓縮apk尺寸,androidapk
在Android中調用動態庫文件(*.so)都是通過jni的方式,而且往往在apk或jar包中調用so文件時,都要將對應so文件打包進apk或jar包,工程目錄下圖:
以上方式的存在的問題:
1、缺少靈活性比較類似靜態載入了(不是靜態載入),能載入的so文件綁定死了;
2、但so文件很多或很大時,會導致對應的apk和jar包很大;
3、不能動態的對so文件更新;
Android中載入so文件的提供的API:
void System.load(String pathName);
說明:
1、pathName:文件名+文件路勁;
2、該方法調用成功後so文件中的導出函數都將插入的系統提供的一個映射表(類型Map);
看到以上對System.load(String pathName);的函數說明可定有人會想到將so文件放到一個指定的目錄然後再通過參數pathName直接引用該目錄的路勁和對應的so文件問題不就解決了嗎?
這里有個問題被忽略了,那就是System.load只能載入兩個目錄路勁下的so文件:
1、/system/lib ;
2、安裝包的路勁,即:/data/data/<packagename>/…
而且這兩個路勁又是有許可權保護的不能直接訪問;
問題解決方法:
先從網路下載so文件到手機目錄(如:/test/device/test.so) –> 將test.so載入到內存(ByteArrayOutputStream) –> 然後保存到對用安裝包目錄;
具體代碼如下:
try {
String localPath = Environment.getExternalStorageDirectory() + path;
Log.v(TAG, "LazyBandingLib localPath:" + localPath);
String[] tokens = mPatterns.split(path);
if (null == tokens || tokens.length <= 0
|| tokens[tokens.length - 1] == "") {
Log.v(TAG, "非法的文件路徑!");
return -3;
}
// 開辟一個輸入流
File inFile = new File(localPath);
// 判斷需載入的文件是否存在
if (!inFile.exists()) {
// 下載遠程驅動文件
Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");
return 1;
}
FileInputStream fis = new FileInputStream(inFile);
File dir = context.getDir("libs", Context.MODE_PRIVATE);
// 獲取驅動文件輸出流
File soFile = new File(dir, tokens[tokens.length - 1]);
if (!soFile.exists()) {
Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");
FileOutputStream fos = new FileOutputStream(soFile);
Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"
+ tokens[tokens.length - 1]);
// 位元組數組輸出流,寫入到內存中(ram)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fis.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
// 從內存到寫入到具體文件
fos.write(baos.toByteArray());
// 關閉文件流
baos.close();
fos.close();
}
fis.close();
Log.v(TAG, "### System.load start");
// 載入外設驅動
System.load(soFile.getAbsolutePath());
Log.v(TAG, "### System.load End");
return 0;
} catch (Exception e) {
Log.v(TAG, "Exception " + e.getMessage());
e.printStackTrace();
return -1;
}
D. 想請教下各位,android動態載入apk的實現方法
其實有一個很實際的問題就是當你重新做一個功能,比你重用一個功能所花的時間更少的情況下那麼重用還有價值么,以上出現的情況可說是百分百這個問題我早就想明白了,不過不知道怎麼說明白。反正重用就是實驗室里的東西不過不重要啦,反正你的問題就是在android裡面反編譯出xml就好了,如果你非要一條路走到底,不想其他實現的話。
E. 如何更新android系統中到Setting.apk
第一步:
首先要在android源碼根目錄下執行
740 . build/envsetup.sh
741 brunch jordan
這一步其實是全編譯android來,會在根目錄下生成update-cm-7.2.0-RC1-jordan-UNOFFICIAL-signed.zip,這個ROM,用於更新系統。
在以後,其實可以直接
. build/envsetup.sh
來初始化編譯環境。
進入android-cm7/packages/apps/Settings,執行命令mm:
結果如下:
make: Entering directory `/home/neo/defy/android-cm7'
Copying: out/target/common/obj/APPS/Settings_intermediates/emma_out/lib/classes-jarjar.jar
Install: out/target/proct/jordan/system/app/Settings.apk
Copying: out/target/common/obj/APPS/SettingsTests_intermediates/emma_out/lib/classes-jarjar.jar
Install: out/target/proct/jordan/data/app/SettingsTests.apk
make: Leaving directory `/home/neo/defy/android-cm7'
可見,在out/target/proct/jordan/system/app/目錄下 生成了Settings.apk文件。
第二步:
在目錄android-cm7/out/target/proct/jordan/system/app下執行
# adb remount
將文件系統重新掛載,獲得文件系統到讀寫許可權,再執行push,將Settings.apk載入到目標路徑,覆蓋原來到Settings,
# adb push Settings.apk /system/app
3122 KB/s (4576533 bytes in 1.431s)
手機上重新打開設置,就可以看見剛才修改到效果了。
F. 如何把電腦里的apk文件載入到安卓模擬器里
模擬後不是能聯網嗎,就可以下載啦,先下個文件管理的東西,再用文件管理打開電腦里的apk文件,或者直接從網上下,方便多了
G. android 怎麼動態更新apk中jar包
核心類
1.1 DexClassLoader類
可以載入jar/apk/dex,可以從SD卡中載入為安裝的apk。
1.2 PathClassLoader類
只能載入已經安裝到Android系統中的apk文件。
一、正文
1.1
類似於eclipse的插件化實現, 首先定義好介面, 用戶實現介面功能後即可通過動態載入的方式載入jar文件, 以實現具體功能。 注意 , 這里的jar包需要經過android dx工具的處理 , 否則不能使用。
H. 如何動態載入android的so文件,如何壓縮apk尺寸
1、去除不必要的依賴,檢查所有直接和間接的依賴關系
2、去除不用的資源,asset下的文件沒用的就刪掉,res下的,尤其是圖片,沒用的就刪,在build.gradle中release標簽里加上shrinkResources true,沒有的資源就不會被打到包里了
3、啟用代碼混淆,混淆不僅可以防止反編譯,也可以減小包的體積,它主要是把包里的dex文件變小了
I. android 怎麼載入未安裝的apk資源
准備
准備被調用Android工程:TestB
ITest
public interface ITest {
String getMoney();
}
TestBActivity
public class TestBActivity extends Activity implements ITest {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public String getMoney() {
return "1";
}
}
代碼說明:很簡單的代碼。將生成後的TestB.apk拷貝到SD卡的根目錄下。
調用 :
調用工程TestA
public class TestAActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String path = Environment.getExternalStorageDirectory() + "/";
String filename = "TestB.apk";
DexClassLoader classLoader = new DexClassLoader(path + filename, path,
null, getClassLoader());
try {
Class mLoadClass = classLoader.loadClass("com.nmbb.TestBActivity");
Constructor constructor = mLoadClass.getConstructor(new Class[] {});
Object TestBActivity = constructor.newInstance(new Object[] {});
Method getMoney = mLoadClass.getMethod("getMoney", null);
getMoney.setAccessible(true);
Object money = getMoney.invoke(TestBActivity, null);
Toast.makeText(this, money.toString(), Toast.LENGTH_LONG).show();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
執行的時候可以發現會自動生成TestB.dex文件。動態載入方面還可以搜索一下"Java動態載入"方面的資料,很有參考價值。
J. android 怎麼動態載入jar
核心類 1.1 DexClassLoader類 可以載入jar/apk/dex,可以從SD卡中載入為安裝的apk。 1.2 PathClassLoader類 只能載入已經安裝到Android系統中的apk文件。 一、正文 1.1 類似於eclipse的插件化實現, 首先定義好介面, 用戶實現介面功能後即可通過動態載入的方式載入jar文件, 以實現具體功能。 注意 , 這里的jar包需要經過android dx工具的處理 , 否則不能使用。