Android Studio 將項(xiàng)目中封裝好的 Module 打包成 .jar 包 并混淆

一可缚、Android Studio 默認(rèn)自動(dòng)生成的 jar 包

眾所周知 Android Studio 會(huì)在 library 所依賴的 app運(yùn)行 或 build 之后自動(dòng)生成 jar 包,路徑為 Module根目錄/build/intermediates/packaged-classes/debug/classes.jar型型,這樣生成的jar是可以用的,但不是我們可以控制的吩愧,所以我們需要通過(guò)其他方式來(lái)生成jar包寇甸。


注意:
若發(fā)現(xiàn) Android Studio 項(xiàng)目 packaged-classes 文件夾下沒(méi)有 release 目錄,可能是沒(méi)有將 module 添加到主 module 依賴中虎韵。

方式1:主module右鍵 --> 倒數(shù)第二個(gè)Open Module Setting--> 上面最后一個(gè)選項(xiàng)Dependencies-->右邊綠色加號(hào)-->Module dependency......然后確定

方式2:主 Module 的 gradle 的 dependencies(平時(shí)添加第三方庫(kù)的地方)中加上 implementation project(':librarytest')
點(diǎn)擊 assembleRelease 生成 release 包易稠,packaged-classes 目錄下就會(huì)生成 release 目錄了


assembleRelease

二、自定義生成 jar 包

方式 A :點(diǎn)擊 Android Studio 右側(cè)(一般在這個(gè)位置)的 Gradle 面板包蓝,在項(xiàng)目或者該類庫(kù)的目錄中找到 Tasks -> other -> makeJar 命令驶社,雙擊這個(gè)makeJar之后等一會(huì)就會(huì)編譯好jar包企量。
打包成功后:在配置的指定目錄下生成jar包

方式 B :通過(guò) cmd 命令行,在項(xiàng)目根目錄下亡电,執(zhí)行 gradlew makeJar 命令届巩,看到編譯完成的信息以后就OK了,也能生成一樣的jar包份乒,和直接使用①中的方式是等價(jià)的姆泻。

注意:使用此方式前要配置好 gradle 的“ 環(huán)境變量 ”,否則直接在項(xiàng)目根目錄下找不到這個(gè)命令冒嫡。使用 cmd 比較費(fèi)勁拇勃,不推薦。

方式 C :在 Android Studio 終端窗口中輸入 gradlew makeJar 命令孝凌。
首先方咆,需要將待打包 module 項(xiàng)目中的 build.gradle 文件進(jìn)行修改,如下圖:


module build.gradle

其次蟀架,在 library 的 app:build.gradle 中添加如下代碼:

方法一:

// 方法一
def _BASENAME = "LibraryT"; //  jar包名字可以自由更改
def _VERSION = "_V1.0";
def _DestinationPath = "build"; //生成jar包的位置
def zipFile = file('build/intermediates/packaged-classes/debug/classes.jar'); // 待打包文件位置

task deleteBuild(type:Delete){
    delete _DestinationPath + _BASENAME + _VERSION + ".jar"
}
task makeJar(type:Jar){
    from zipTree(zipFile)
    from fileTree(dir:'src/main',includes:['assets/**']) //將assets目錄打入jar包
    baseName = _BASENAME + _VERSION
    destinationDir = file(_DestinationPath)
}
makeJar.dependsOn(deleteBuild, build)
LibraryT_V1.0.jar

方法二:

首先瓣赂,在方法一的基礎(chǔ)上把在 library 的 app:build.gradle 中添加的代碼修改為如下:

task clearJar(type: Delete) {
    delete 'build/libs/LibraryT.jar'
    delete 'libs/LibraryT.jar'
}
//打包任務(wù)
task makeJar(type: Jar) {
    //指定生成的jar名
    baseName 'LibraryT'
    //從哪里打包c(diǎn)lass文件
    from('build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/example/eagleview/librarytest')
    //release 路徑,這個(gè)classes的路徑不一定是從javac文件下片拍,也有可能在 intermediates 目錄下煌集,所以只要找到相應(yīng)的路徑修改即可 
//    from('build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/example/eagleview/librarytest')
    //打包到j(luò)ar后的目錄結(jié)構(gòu)
    into('com/example/eagleview/librarytest/')
    //去掉不需要打包的目錄和文件
    exclude('BuildConfig.class', 'R.class')
    //去掉R$開(kāi)頭的文件
    exclude { it.name.startsWith('R$'); }
}
makeJar.dependsOn(clearJar, build)

LibraryT.jar

這個(gè)方法可以解決com.android.dex.DexException: Multiple dex files define 此類的錯(cuò)誤
原因是sdk 的jar包中打入了BuildConfig.class,解決方法很簡(jiǎn)單:解包捌省,刪除里面的 BuildConfig.class苫纤,然后重新打包 jar。
具體如下:

  1. 解壓jar包: jar xf xxx.jar
  2. 刪除解壓后目錄里面的//BuildConfig.class
  3. 重新打包: jar cvf xxx.jar *
    當(dāng)然這樣的方法有點(diǎn)粗糙纲缓,而且我們也絕對(duì)不希望給其他開(kāi)發(fā)者帶來(lái)困擾卷拘,所以我們可以有選擇的將我們需要的class文件打包,把類似 BuildConfig.class / R.class ......文件排除在打包祝高,完美解決問(wèn)題

在proguard-rules.pro文件中配置混淆文件

# 表示混淆時(shí)不使用大小寫混合類名
-dontusemixedcaseclassnames

# 表示不跳過(guò)library中的非public的類
-dontskipnonpubliclibraryclasses

# 打印混淆的詳細(xì)信息
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize

# 表示不進(jìn)行校驗(yàn),這個(gè)校驗(yàn)作用 在java平臺(tái)上的
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.
#使用注解需要添加
-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
#指定不混淆所有的JNI方法
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
#所有View的子類及其子類的get栗弟、set方法都不進(jìn)行混淆
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
# 不混淆Activity中參數(shù)類型為View的所有方法
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
# 不混淆Enum類型的指定方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 不混淆Parcelable和它的子類,還有Creator成員變量
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# 不混淆R類里及其所有內(nèi)部static類中的所有static變量字段
-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
# 不提示兼容庫(kù)的錯(cuò)誤警告
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}


###########################以下是需要手動(dòng)的混淆配置協(xié)議###############################


-libraryjars "C:\Program Files\Java\jre1.8.0_191\lib\rt.jar"
#-libraryjars "C:\Users\admin\AppData\Local\Android\sdk\platforms\android-26\android.jar"
# 注意:以上兩個(gè)路徑需要將以上路徑是自己jar包的位置工闺,需要根據(jù)自己情況進(jìn)行修改乍赫,如果報(bào)重復(fù)配置的錯(cuò)誤,注釋掉即可

#代碼迭代優(yōu)化的次數(shù)陆蟆,默認(rèn)5
-optimizationpasses 5
#混淆時(shí)不會(huì)產(chǎn)生形形色色的類名
-dontusemixedcaseclassnames


#忽略警告
-ignorewarnings
#以下是不需要混淆的文件
 -keep class com.android.sdk.demo.LogUtils{
     *;
 }
 -keep class com.android.sdk.demo.StorageUtils{
     *;
 }

三雷厂、直接使用 aar 包

將被嵌入的應(yīng)用打包成 aar 包,這也是 Android Studio 的一種新特性遍搞,可以將應(yīng)用所使用的資源性文件一起打包罗侯。編譯即可打包生成 aar 包,而且也不用擔(dān)心漏掉資源問(wèn)題溪猿。

如果Project 中 Module 是一個(gè)應(yīng)用钩杰,則在 Module 的 build.gradle 文件中定義屬性為:apply plugin: 'com.android.application'纫塌;而如果 Mudule 是一個(gè)被引用的依賴 lib 庫(kù)的話,則在 Module 的 build.gradle 文件中定義屬性為: apply plugin: 'com.android.library讲弄;所以當(dāng)我們將應(yīng)用 Module 打包出 aar 文件的時(shí)候措左,需要修改類型屬性。正常情況下避除,直接重新編譯 Module怎披,生成的 aar 包在 Module 根目錄的/build/outputs/aar/,如下圖:


aar 包

下面介紹將 aar 包添加到其他 Android 工程:
  首先瓶摆,將 aar 包復(fù)制到 libs 目錄下
  其次凉逛,配置build.gradle文件:
在 要調(diào)用aar 包的 build.gradle 中加入:

apply plugin: 'com.android.application'  
  
android {  
    ...
    repositories {  
        flatDir {  
            dirs 'libs'  
        }  
    }  
}  
  
dependencies {  
    ...
    compile(name:'librarytest-release', ext:'aar')  
}

最后,clean一下工程群井,重新編譯状飞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市书斜,隨后出現(xiàn)的幾起案子诬辈,更是在濱河造成了極大的恐慌,老刑警劉巖荐吉,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焙糟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡样屠,警方通過(guò)查閱死者的電腦和手機(jī)穿撮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞧哟,“玉大人混巧,你說(shuō)我怎么就攤上這事∏诳” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵秘蛔,是天一觀的道長(zhǎng)陨亡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)深员,這世上最難降的妖魔是什么负蠕? 我笑而不...
    開(kāi)封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮倦畅,結(jié)果婚禮上遮糖,老公的妹妹穿的比我還像新娘。我一直安慰自己叠赐,他們只是感情好欲账,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布屡江。 她就那樣靜靜地躺著,像睡著了一般赛不。 火紅的嫁衣襯著肌膚如雪惩嘉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天踢故,我揣著相機(jī)與錄音文黎,去河邊找鬼。 笑死殿较,一個(gè)胖子當(dāng)著我的面吹牛耸峭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淋纲,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼劳闹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了帚戳?” 一聲冷哼從身側(cè)響起玷或,我...
    開(kāi)封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎片任,沒(méi)想到半個(gè)月后偏友,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡对供,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年位他,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片产场。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鹅髓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出京景,到底是詐尸還是另有隱情窿冯,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布确徙,位于F島的核電站醒串,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鄙皇。R本人自食惡果不足惜芜赌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伴逸。 院中可真熱鬧缠沈,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至禽篱,卻和暖如春畜伐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背躺率。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工玛界, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悼吱。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓慎框,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親后添。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笨枯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料遇西? 從這篇文章中你...
    hw1212閱讀 12,693評(píng)論 2 59
  • 說(shuō)明 本文主要介紹和Gradle關(guān)系密切馅精、相對(duì)不容易理解的配置,偏重概念介紹粱檀。部分內(nèi)容是Android特有的(例如...
    jzj1993閱讀 15,573評(píng)論 1 62
  • 參考 中文官網(wǎng)構(gòu)建指南:https://developer.android.google.cn/studio/bu...
    FinalSky閱讀 5,316評(píng)論 0 16
  • 在期待與悶熱中開(kāi)始了學(xué)習(xí)洲敢,在留戀與煙雨中結(jié)束了行程。 剛下火車只有熱茄蚯,濕熱的天氣讓我們幾個(gè)人沒(méi)法適應(yīng)压彭,不想出門,只...
    春夏AI閱讀 201評(píng)論 0 2