Android Library 打 jar 包
正确的 library 项目的 build.gradle 中有这样的代码标志
apply plugin: 'com.android.library'
接下来就是打 Jar 包了
在需要打 Jar 的 library 项目中的 build.gradle 文件最下面也就是 dependencies {} 下面
看一个完整的示例
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
task makeJar(type: Copy) {
delete 'build/libs/' //删除已经存在的jar包
from('build/intermediates/packaged-classes/release/') //已经帮我们打好的 jar 的路径
into('build/libs/') //要将jar包保存的目录
include('classes.jar')//设置过滤,只打包classes文件
rename('classes.jar', 'mylibrary.jar')//重命名,mylibrary.jar 根据自己的需求设置
}
makeJar.dependsOn(build)
接下来就是执行命令
mac : 在当前项目的根目录下执行
./gradlew makeJar
然后等待编译成功之后,就可以在前面指定的目录中看到我们想要的 jar 包了。
Jar 包混淆
有时候我们打出来的 Jar 想将代码混淆,该怎么做呢?
这个时候我们还是再 library 项目的 build.gradle 的文件中做文章。
看改动如下
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
task makeJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") {
injars 'build/intermediates/packaged-classes/release/classes.jar'
outjars 'build/outputs/modify.jar'
configuration 'proguard-rules.pro'
}
通过对比,不难发现,其实改动的只是 task makeJar()方法
其实只是在原有的 jar 上加了混淆,也就是引入了这样的代码
configuration 'proguard-rules.pro'
也就是我们的混淆文件
至于proguard-rules.pro
里面的内容就需要我们自己根据项目中的内容去写了
1.首先可以把AndroidStudio 自带的标准内容写入,如下:
#表示混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
#表示不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
#打印混淆的详细信息
-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
##表示不进行校验,这个校验作用 在java平台上的
-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
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-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
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
-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.
-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>(...);
}
2.一般都需要的如下(其中 xxx 替换成你自己本地的相关路径)
#引入依赖包rt.jar(jdk路径)
-libraryjars /xxx/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar
#引入依赖包android.jar(android SDK路径)
-libraryjars /xxx/Android/sdk/platforms/android-29/android.jar
#忽略警告
-ignorewarnings
#保证是独立的jar,没有任何项目引用,如果不写就会认为我们所有的代码是无用的,从而把所有的代码压缩掉,导出一个空的jar
-dontshrink
#保护泛型
-keepattributes Signature
3.最后加上我们不希望被混淆的类或者方法(根据自己的实际需求添加,比如入口什么的)
# 不希望被混淆的类
-keep class com.cml.lib.M
# 不希望被混淆的方法
-keep class com.cml.lib.M {
void a(...);
}
好了,接下来再次再项目的根目录执行命令
./gradlew makeJar
然后等待编译完成,看看输出出来的 Jar 就已经被混淆过了。
打 aar 包
aar 相对于 Jar 来说可以携带更多的东西,比如资源文件、Manifest文件等。
aar 的生成就简单多了,用 AndroidStudio 就可以帮我们完成。
点 AndroidStudio 右上角有一个 Gradle(竖这放的)–> 项目名 –> library 名–> Tasks –> build –> assemble , 双击最后的这个 assemble 就完成了
aar 的输出路径在 library 的 build/outputs/aar/ 下面 会发现有debug和 release 两个版本,取自己需要的就行了,如果不知道需要什么,那么取 release 版本即可
但是我们查看发现这个 aar 并没有被混淆,那么怎么混淆呢?
其实跟我们 apk 的混淆一样了,有一个开关需要打开在 library 的 build.gradle 中
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
对,就是这个minifyEnabled
设置为 true 即可打开混淆了。
但同样不要忘记proguard-rules.pro
文件里面的内容的编写哦,具体的编写方法,上面已经说过了,跟前面的 Jar 混淆方式一样。