編輯:Android開發實例
最近突發奇想,想做一個插件框架,就是實現一個微內核,所有擴展功能都通過下載插件加載的方式來實現,原理跟現在用的eclipse差不多。要做到這些動態加載類少不了,就是內核上事先定義好接口,通過網絡或其他方式下載的插件要實現這些接口,只要定義好規則,系統就可以使用這些插件了。
Android動態加載不是程序本身的類,要用到PathClassLoader和DexClassLoader, 兩個類的構造方法分別是:
- PathClassLoader(String path, ClassLoader parent);
- DexClassLoader(String dexPath, String dexOutputDir, String libPath, ClassLoader parent);
網上查了一下資料,PathClassLoader的類加載路徑必須在/data/app路徑下。DexClassLoader可以加載sdcard目錄下的apk或jar文件,編譯好的類不能立即使用,要通過dx工具轉換為.dex格式的。一切實驗都很順利,但到類型轉換這步出錯了,代碼如下:
- DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, ClassLoader.getSystemClassLoader());
- Class<?> clazz = loader.loadClass("czh.plugin.Dog");
- Animal dog = (Animal)clazz.newInstance();
- dog.sayHello();
上述代碼中類Dog繼承自類Animal,執行這些代碼的apk定義了Animal,但Dog是在dog.apk定義的,dog.apk裡面也定義了Animal。問題就出來了,在clazz實例化一個對象想轉換為Animal時,程序報了ClassCastException異常。想了一下,實例化的Dog對象應該只認識dog.apk裡的Animal類是它的父類,而認為執行上述代碼的apk裡Animal類不是它的父類。於是俺把dog.apk裡的Animal類去掉,重新用dx打包放到sdcard目錄下,結果這次報了不能找到類czh.plugin.Dog的異常,也就是無法加載類Dog。
查看了Class類forName(String name)方法的源代碼,發現它們加載類用的不是ClassLoader.getSystemClassLoader(), 而是VMStack.getCallingClassLoader(), 於是俺把代碼改了一番,終於運行通過了:
- DexClassLoader loader = new DexClassLoader("/sdcard/dog.apk", "/sdcard", null, VMStack.getCallingClassLoader());
Java的ClassLoader其實是一個鏈式結構,加載類的時候優先從最頂層的ClassLoader開始加載,若無法找到該類才嘗試下一級ClassLoader加載。上述代碼保證了類Animal能被VMStack.getCallingClassLoader()加載,類Dog被loader加載,同時這兩個類在同一個ClassLoader加載鏈中,確保了它們的父子關系能正常識別,這樣就不會發生ClassCastException異常了。
不過VMStack這個類被標識為deprecated, 將來可能被google去除不給我們使用,到時候就要想些方法來克服這點困難了。
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
SlidingDrawer隱藏屏外的內容,並允許用戶通過handle以顯示隱藏內容。它可以垂直或水平滑動,它有倆個View組成,其一是可以拖動的handle,其二
Android對這種方法進行了封裝,我們沒有權限去調用這個方法,所以我們只能通過AIDL,然後利用Java的反射機制去調用系統級的方法。 下面上代碼:(注釋比較詳
本文將引導大家做一個音樂播放器,在做這個Android開發實例的過程中,能夠幫