Android Studio 中合并jar包 - fatjar插件

jar.png

在開發(fā)中我們經(jīng)常需要將某個模塊以JAR包的形式輸出,在打包的同時需要將它所依賴的多個JAR都整合到本JAR中,這樣我們就可以直接使用“java -jar”命令執(zhí)行它,而不用設置classpath或者部署所依賴的JAR,別的開發(fā)者也可以很方便的引用這個JAR。

在eclipse中有一個fatjar的插件可以很方便的完成這個需求,但是在android studio中我還沒有發(fā)現(xiàn)這樣的插件。想了下這類插件的原理也就是簡單的文件讀寫,所以決定自己動手實現(xiàn)一個。

本文出處:http://www.itdecent.cn/p/be46b3891d0e

JAR文件格式

動手寫代碼之前我們先了解下JAR文件格式。在軟件領(lǐng)域,JAR文件(Java歸檔:Java ARchive)是一種軟件包文件格式,通常用于聚合大量的Java類文件、相關(guān)的元數(shù)據(jù)(manifest文件)和資源(文本、圖片等)文件到一個文件,便于分發(fā)的Java平臺的應用軟件或庫。JAR文件是一種歸檔文件,以ZIP格式構(gòu)建,以.jar為文件擴展名。用戶可以使用JDK自帶的jar命令創(chuàng)建或提取JAR文件。也可以使用其他zip壓縮工具,不過壓縮時zip文件頭里的條目順序很重要,因為Manifest資源配置文件常需放在首位。

jar_format.png

Manifest資源配置文件是JAR中包含的特殊文件,它被用來定義擴展或檔案打包相關(guān)數(shù)據(jù)。Manifest文件中的條目定義這個JAR文件如何被使用。例如,類路徑條目由其他JAR文件的絕對或相對路徑的列表組成,用于指定在加載本JAR文件時同時加載的其他JAR文件。雖然旨在簡化JAR的使用,但在實踐中證明Manifest文件是非常脆弱的,因為入口點JAR在創(chuàng)建時依賴于所有相關(guān)的JAR的確切位置。一旦需要更改依賴庫的位置,必需重建Manifest文件。本文實現(xiàn)的fatjarCreator工具,將所依賴的相關(guān)JAR都打包到本JAR中,可以避免這樣的問題。

manifest.png

fatjarCreator工具的制作

因為jar文件實際是一個文件包,所以jar文件讀寫和普通的文件讀寫有一定的區(qū)別,我們需要先將jar包中的每個文件遍歷出來再依次進行文件讀寫。幸運的是軟件包 java.util.jar 提供了讀寫JAR 文件的類,如JarFile.class、JarOutputStream.class、Manifest.class、JarEntry.class等。這個合并工具本身也是用Java寫的,完成后也是一個jar包,我將它命名為fatjarCreator.jar。核心邏輯如下:

    public void create(ArrayList<String>jarPaths, String output) {
        String jarPath = "";
        Manifest manifest = getManifest();   //獲取outJar的manifest
        FileOutputStream fos = new FileOutputStream(output);
        JarOutputStream jos = new JarOutputStream(fos, manifest);  //根據(jù)輸出路徑和manifest創(chuàng)建輸出流
        for (int i = 0; i < jarPaths.size(); i++) {
            jarPath = jarsPaths.get(i);
            JarFile jarFile = new JarFile(jarPath);
            Enumeration<?> entities = jarFile.entries();  
            while (entities.hasMoreElements()) {  
                JarEntry entry = (JarEntry) entities.nextElement();  //遍歷jar文件中的每個文件節(jié)點

                //在寫目錄中的文件時,目錄會自動創(chuàng)建
                //meta-inf使用我們上面獲取的manifest,不使用之前的了meta-inf
                if (entry.isDirectory() || entry.getName().toLowerCase().startsWith("meta-inf")) {  
                    continue;  
                }  

                InputStream in = jarFile.getInputStream(entry);
                copyData2Jar(in, jos, entry.getName());
            }  

            jarFile.close();  
        }
    } 

    private void copyData2Jar(InputStream in, JarOutputStream jos, String newEntryName) {
        int bufferSize;  
        byte[] buffer = new byte[1024]; 
   
        jos.putNextEntry(new JarEntry(newEntryName));  //在outJar中的創(chuàng)建文件節(jié)點

        while ((bufferSize = in.read(buffer, 0, buffer.length)) != -1) {  
             jos.write(buffer, 0, bufferSize);  
        }  

        in.close();  
        jos.closeEntry();  
    }

    private Manifest getManifest() {  
        Manifest manifest = new Manifest();  
        Attributes attribute = manifest.getMainAttributes();  
        attribute.putValue("Manifest-Version", "1.0");  
        attribute.putValue("Created-By","fat jar plugin");  
        return manifest;  
    }  

同理我們也可以將一些資源(文本、圖片等)文件打到JAR包中。這樣合并JAR文件的方法我們就寫好了,使用時只需要傳入待合并的JAR文件的路徑和輸出文件的路徑就可以了。通常需要合并的文件較多,如果使用命令行傳入?yún)?shù)的方式,那么執(zhí)行命令會很長,為了更方便的使用,我們可以用配置文件來傳入文件路徑。我這里使用了如下xml文件來作為配置文件,增刪改查合并JAR文件時候只需要修改對應的配置文件即可。

<?xml version="1.0" encoding="UTF-8"?>
<files>
    <jars> 
       <jar path="D:\\codes\\libs\\base.jar"/>
       <jar path="D:\\codes\\libs\\cardboard.jar"/>
       <jar path="D:\\codes\\libs\\mAppTracker.jar"/>
       <jar path="D:\\codes\\libs\\mvvtracker.jar"/>
       <jar path="D:\\codes\\build\\intermediates\\bundles\\release\\classes.jar"/>
    </jars>
    <assets path="D:\\codes\\assets"/>
</files>

到這里我們就可以將實現(xiàn)的代碼輸出成一個可執(zhí)行的fatjarCreator.jar。把它和上面?zhèn)€的配置文件fatjar_config.xml放在同一目錄下,然后雙擊fatjarCreator.jar或者命令行執(zhí)行“Java -jar fatjarCreator.jar”,我們都可以在我們設置的輸出路徑下看到合并后的JAR文件了。

配置gradle

我們的目的是想在Android Studio中更方便的合并JAR文件,現(xiàn)在合并的功能已經(jīng)實現(xiàn)了,如何才能在AS中調(diào)用這個小工具呢?在module的build.gradle中創(chuàng)建一個名為createFatjar的task。然后我們可以在命令行中執(zhí)行“gradle createFatjar”命令或者在AS右邊的gradle欄中雙擊createFatjar來執(zhí)行合并任務。需要把fatjarCreator.jar和fatjar_config.xml放在build.gradle所在目錄。

task createFatjar (type: JavaExec) {
  javaexec { 
    main="-jar";        
    args=["fatjarCreator.jar"];
  }
}

代碼

為了文章的簡潔,文中的示例代碼省略了很多,如入口方法,xml的解析等。想要獲取完整項目代碼的同學可以點擊代碼獲取。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容