一可缚、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 目錄了
二、自定義生成 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)行修改,如下圖:
其次蟀架,在 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)
方法二:
首先瓣赂,在方法一的基礎(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)
這個(gè)方法可以解決com.android.dex.DexException: Multiple dex files define 此類的錯(cuò)誤
原因是sdk 的jar包中打入了BuildConfig.class,解決方法很簡(jiǎn)單:解包捌省,刪除里面的 BuildConfig.class苫纤,然后重新打包 jar。
具體如下:
- 解壓jar包: jar xf xxx.jar
- 刪除解壓后目錄里面的//BuildConfig.class
- 重新打包: 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 包添加到其他 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一下工程群井,重新編譯状飞。