Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android app中加載jar插件

Android app中加載jar插件

編輯:Android開發實例

插件的引入

1、UI方面有些自定義的通用控件代碼,並不局限於一個項目中使用,當需要共享使用時雖然可以采用源碼方式合入新項目,但是這種原始方式增加代碼布局上的復雜程度的同時,也增大了通用控件的不安全性。 2、有些功能性模塊,或是第三方開發,或是分階段開發的,為了方便程序的功能擴展,我們同樣考慮將功能代碼封裝為插件包的形式。 那麼在Android中是否支持插件呢?也就是是否支持類似Windows和Symbian平台的lib和dll等庫方式呢?答案是肯定的,在Android中支持的插件庫,可以是由C/C++開發的JNI形式,也可以是由java代碼開發的jar形式(也可以是android封包完成的apk文件)。由於JNI需要涉及Android NDK,這裡不做介紹,本文只針對jar插件。 加載jar插件的方式 雖然在加載jar插件方式之前,我們應該考慮jar插件的創建,但是由於jar加載方式的不同,決定了jar插件創建形式的不同。目前加載jar插件的方式有兩類:一類是跟加載SDK api的Android.jar一樣的靜態加載方式;另一類是運行時動態加載方式。前者是編譯過程中就必須要jar文件存在,後者是運行時通過反射機制來動態調用。下面我們分別闡述。 靜態加載jar插件 靜態jar插件的創建 靜態jar插件的創建,可以只是由一個簡單的java類文件編譯生成,也可以從一個完整的工程中導出生成。 假設有一個沒有用到Android API的 test.java文件放置在c盤根目錄下面,那麼在安裝jdk的PC上我們可以通過cmd命令行來生成一個jar文件 //編譯test.java,生成test.class C:\>javac test.java //壓縮test.class生成jar文件 C:\>jar cvf test.jar test.class 標明清單(manifest) 增加:test.class(讀入= 267) (寫出= 213)(壓縮了 20%) //查看生成的jar文件中具體有哪些內容 C:\>jar tvf test.jar      0 Fri Sep 23 11:21:34 CST 2011 META-INF/     75 Fri Sep 23 11:21:34 CST 2011 META-INF/MANIFEST.MF    267 Thu Sep 22 17:56:42 CST 2011 test.class 通過如上步驟一個最簡單jar插件就生成了。下面在看如何從一個完整工程中生成一個jar文件,當然也可以通過cmd命令行的方式來實現,但是對於工程來說,涉及代碼文件多,在Eclipse中又提供了簡易操作的情況下,我們自然優先選擇Eclipse來圖形化實現jar文件的生成。本想自己按步驟小結下,但是發現網上很多博客整理的很詳細了,我在這裡就引用http://hi.baidu.com/lovewjlove/blog/item/95d74560ebacdbd68db10d90.html 博文中的內容吧。 1. 首先在Eclipse中打開項目, 右鍵點擊項目,選擇“Export”; 2. 選擇Java/JAR file,Next; 3. Select the resources to export中可以選擇你想要包含的項目文件夾,一些不必要的文件夾就無需放進去了,免得增大空間; 這裡有幾個選項:     * Export generated class files and resources 表示只導出生成的.class文件和其他資源文件     * Export all output folders for checked projects 表示導出選中項目的所有文件夾     * Export java source file and resouces 表示導出的jar包中將包含你的源代碼*.java,如果你不想洩漏源代碼,那麼就不要選這項了     * Export refactorings for checked projects 把一些重構的信息文件也包含進去 在Select the export destination中選擇導出的jar的路徑,Next 4. 下一頁可以選擇是否導出那些含有警告warning或者錯誤errors的*.class文件。一般不用理他,Next 5. 下一個頁面裡可以對項目做一些配置     * Generate the manifest file是系統幫我們自動生成MANIFEST.MF文件,如果你的項目沒有引用其他class-path,那可以選擇這一項;     * Use existing mainfest from workspace。這是可以選擇我們自定義的.MF文件,格式如上所寫;     * Seal content。要封裝整個jar或者指定的包packet;     * Main class。這裡可以選擇你的程序入口,將來打包出來的jar就是你這個入口類的執行結果; 配置完點擊Finish,工程的jar文件就生成了。 博文中只是針對java工程,對於android工程我們自然也是可以通過上述方法完成靜態jar文件的生成。 靜態jar插件的使用 通過上面靜態jar插件的創建步驟,我們生成了一個drawcolor.jar的jar插件,下面我們來演示下如何將這個文件加載到Android app中進行使用。 首先,拷貝jar插件至工程目錄。在android工程根目錄創建一個lib文件夾,將該drawcolor.jar拷貝至lib文件夾下; 其次,工程中添加jar插件。右擊工程,通過屬性菜單,打開Java Build Path對話框,選中Libraries,添加JARS,在彈出的對話框中選擇lib/drawcolor.jar文件(也可以通過項目右鍵點擊Build Path,Build Path–> Libraries–> Add JARs,選擇第三方的jar包,),結果如下   第三,調用jar中的操作。通過上述步驟之後,在Eclipse的Project Explorer下面就可以看到jar包中的類和成員了,與使用Android.jar內的API一樣使用,具體就不給出示例了。   第四,將添加的jar打包到apk中。由於SDK的API在運行環境中(模擬器和手機上)已經有插件存在了,所以我們不用打包到apk中,而我們自己添加的jar,就必須要打包到apk中,否則運行時會報沒有找到包的錯誤。打包到apk需要做如下操作 在工程目錄下找到.classpath文件,因為我們這裡添加的jar位於lib/drawcolor.jar,所以查看文件中是否有如下一行        <classpathentry kind="lib" path="lib/drawcolor.jar"/> 假如有就可以了,假如是其他的,就要把他更改過來,比如http://www.yoyong.com/archives/tag/android-%E6%89%93%E5%8C%85%E7%AC%AC%E4%B8%89%E6%96%B9jar博文中提到的一樣。 懷疑這個跟Eclipse的版本有關吧,我的編譯環境下,這個在工程中添加jar插件步驟時已經在工程的.classpath文件修改為需求的樣子了。 以上就實現了靜態加載jar插件。 動態加載jar插件 動態jar插件的創建 動態jar插件的創建相對比靜態jar多了一個步驟,因為Android虛擬機是基於dex的,所以我們的class不能簡單的調用jar命令壓縮就可以了,而是需要使用sdk\platform-tools目錄下的dx工具來進行類型轉換。下面演示單一類文件AddFunc.java的生成jar插件使用命令行的過程。 <!--[if !supportLists]-->1、 <!--[endif]-->使用javac命令編譯生成AddFunc.class文件 <!--[if !supportLists]-->2、 <!--[endif]-->由於AddFunc類的包目錄為com.demo.jar,所以需要將AddFunc.class文件拷貝至sdk\platform-tools\com\demo\jar文件夾下面 <!--[if !supportLists]-->3、 <!--[endif]-->使用dx命令,生成jar插件文件,上述步驟的命令如下 C:\>javac AddFunc.java   C:\>dx --dex --output=AddFunc.jar com/demo/jar/AddFunc.class   C:\>jar tvf D:\Android\sdk\platform-tools\AddFunc.jar     72 Fri Sep 23 14:28:48 CST 2011 META-INF/MANIFEST.MF    964 Fri Sep 23 14:28:50 CST 2011 classes.dex 通過上述步驟在sdk\platform-tools上面就有一個AddFunc.jar文件了。在這裡需要說明的是AddFunc.class必須按照包名放置,否則生成jar會報錯。 其實假如本身就在Android工程下面,那麼可以現在eclipse下面先編譯程序,後在Bin目錄下面,自然就按包名,放置了class文件,再將需要的class文件包含文件目錄拷貝至sdk\platform-tools目錄下就好了。假設我們需要打包兩個class,就可以通過如下命令實現 C:\>dx --dex --output=AddFunc.jar com/demo/jar/AddFunc.class com/demo/jar/GameView.class 經過查詢,明顯比上面這個classes.dex文件大多了,具體如下 C:\>jar tvf D:\Android\sdk\platform-tools\AddFunc.jar     72 Fri Sep 23 14:38:06 CST 2011 META-INF/MANIFEST.MF  1752 Fri Sep 23 14:38:06 CST 2011 classes.dex 好了,我們需要的動態jar插件就形成了。 動態jar插件的使用 如上所述,我們生成了需要動態jar插件,如同java中動態加載使用ClassLoader類動態加載一樣,在Android我們需要使用DexClassLoader來通過反射機制動態加載。 相對來說假如動態jar插件創建正確,這一步就沒什麼難題了,就全交給代碼來說明吧。 AddFunc的源代碼為 package com.demo.jar;   import android.util.Log;   public class AddFunc {     public AddFunc()     {            Log.i("AddFunc", "AddFunc class Init");     }         public int Add(int a, int b)     {            int c = a + b;            Log.i("AddFunc", "Add result is "+c);            return c;     } } 以上的代碼生成動態jar插件後,在模擬器通過cmd如下命令,將jar插件放置到運行壞境中,本文是將其放置在模擬器的sdcard根目錄,具體如下 C:\>adb push addFunc.jar sdcard/ 6 KB/s (1149 bytes in 0.187s) 這樣,就可以在代碼中使用反射機制調用jar中的方法了,具體的Android工程中動態調用jar插件的代碼如下 package com.demo.jar.runloadjarDemo;   import java.io.File; import java.lang.reflect.Method; import dalvik.system.DexClassLoader; import android.app.Activity; import android.os.Bundle;   public class RunLoadJarDemoActivity extends Activity {     /** Called when the activity is first created. */        Class myClass =null;            @Override     public void onCreate(Bundle savedInstanceState)     {         super.onCreate(savedInstanceState);         setContentView(R.layout.main);         try         {                File file = new File("/sdcard/AddFunc.jar"); //              File file = new File("/sdcard/drawView.apk");                if(file.exists())                {                       DexClassLoader cl = new DexClassLoader(file.toString(), getFilesDir().getAbsolutePath(), null, ClassLoader.getSystemClassLoader().getParent());                         myClass = cl.loadClass("com.demo.jar.AddFunc");                       Object obj = myClass.newInstance();                       Class[] params = new Class[2];                       params[0] = Integer.TYPE;                       params[1] = Integer.TYPE;                       Method action = myClass.getMethod("Add", params);                       int ret = (Integer)action.invoke(obj, 15, 20);                                     }          }         catch (Exception ex)         {                     ex.printStackTrace();         }     } } 其實從原理上來說,如上生成的動態jar插件,跟apk的生成是同一個道理,所以假設我們不想通過繁瑣的dx工具,那麼也可以直接由eclipse生成apk,然後通過動態加載的方法來使用apk中的類和方法,本人測試過也是可行的。 好了,至此將Android app中加載jar插件的問題就介紹到這裡,如果大家覺得如上的代碼調用反射太過繁瑣,那麼可以通過設計接口的方法來將反射變得簡單,至於這個話題就不在本文進行闡述了。

本隨筆原文和demo,詳見鏈接

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved