Android Studio 打包混淆的 SDK

前段时间公司项目需要开发一个 SDK,最后需要打包给其他用户,然而我之前从来没搞过……网上看了一些文章,但总觉得有些七零八落,自己做的过程也是磕磕绊绊,这两天问题总算搞定了,因此在这里做个小结。

整体步骤实现如下:

1 创建 Module

首先在项目中创建一个 Android Library,如图所示:

选择 Android Library:


创建后的项目结构如下:


library 项目结构

此时 mylibrary 目录下的内容是空的。我们要做的就是将需要打包的内容复制到相应目录下。如图所示:

复制代码后的项目结构

注:关于打包,有两种格式:*.jar*.aar
有关二者的区别:简单点理解,前者只包含代码文件;而后者包含(图片、布局等)资源文件。

本例是包含资源文件的,因此最后需要的是 *.aar 格式的包;若打包代码不含资源文件则只复制代码即可。

2 配置文件

PS: 这些配置是为了打包 *.jar 包配置的,若只要导出 *.aar 包,则无需这些配置。

mylibrary 目录下的 build.gradle 中添加如下代码:

task makeJar(type: proguard.gradle.ProGuardTask, dependsOn: "build") {
    injars 'build/intermediates/bundles/default/classes.jar' // 未混淆的jar路径
    outjars 'build/outputs/mylibrary-1.0.0.jar' // 混淆后的jar输出路径
    configuration 'proguard-rules.pro' // 混淆协议
}

或者下面这种格式:

task clearJar(type: Delete) {
    //这行表示如果你已经打过一次包了,再进行打包则把原来的包删掉
    delete 'build/libs/mylibrary-1.0.0.jar'
}

task makeJar(type: Copy) {
    from('build/intermediates/bundles/default/') //这行表示要打包的文件的路径,根据下面的内容,其实是该路径下的classes.jar
    into('build/libs/')  //这行表示打包完毕后包的生成路径,也就是生成的包存在哪
    include('classes.jar')  //看到这行,如果你对分包有了解的话,你就可以看出来这行它只是将一些类打包了
    rename ('classes.jar', 'mylibrary-1.0.0.jar')
}

makeJar.dependsOn(clearJar, build)

本人暂未搞明白二者的区别在哪,只是看起来语法有些不同,但实现效果相同。

注意:
task clearJar 的路径推荐选择 .../bundles/release,若无该路径,可选择 .../bundles/default

此外,build.gradle 中的 minifyEnabled 一般配置为 true (默认为 false ),如下所示:

android {
  ...
  buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

至于作用,实测后发现设置 true 对导出的包进行了压缩。不管 truefalse,混淆的效果都是有的。 proguardFiles 就是指定的混淆协议。

3 配置混淆协议

我们给其他人提供的包是不希望别人看到源码的,因此需要将源码进行混淆。
打开 mylibrary 目录下的 proguard-rules.pro 文件,配置混淆协议,如下:

3.1 Androdi Studio 自带的配置文档

# 表示混淆时不使用大小写混合类名
-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>(...);
}

3.2 自定义配置

# 引入依赖包rt.jar(jdk路径)
-libraryjars /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/rt.jar
# 引入依赖包android.jar(android SDK路径)
#-libraryjars ~/Library/Android/sdk/platforms/android-25/android.jar
# 如果用到Appcompat包,需要引入
#-libraryjars /xxx/xxx/xx/xxx/MyApplication/library-banner/build/intermediates/exploded-aar/com.android.support/appcompat-v7/24.1.1/jars/classes.jar
#-libraryjars /xx/xx/xx/xx/MyApplication/library-banner/build/intermediates/exploded-aar/com.android.support/support-v4/24.1.1/jars/classes.jar

#忽略警告
-ignorewarnings
#保证是独立的jar,没有任何项目引用,如果不写就会认为我们所有的代码是无用的,从而把所有的代码压缩掉,导出一个空的jar
-dontshrink
#保护泛型
-keepattributes Signature

3.3 类和方法相关配置

# 下面两个仅供参考,具体根据实际需求配置

# 不混淆某个类(使用者可以看到类名)
-keep class com.example.mylibrary.MyRelativeLayout

# 不混淆某个类中以 public 开始的方法(使用者可以看到该方法)
-keepclassmembers class com.example.mylibrary.MyRelativeLayout {
    public *;
}

4 混淆打包

在命令行指向下面命令:

// Mac 系统
./gradlew makeJar

// Windows 系统
gradlew makeJar

出现 BUILD SUCCESSFUL 表示成功了(其实就是执行上面配置的 task makeJar)。
或者,点开 Android Studio 右上部分的 Gradle 目录,选择 :mylibrary -> Tasks -> other,如图所示:

makeJar 路径

下滑找到并执行其中的 makeJar 也可以。

执行成功后,打开相应的目录(这里用的 outputs 目录,可改变),即可看到已经生成了 *.jar 包(还有 *.aar 包),如图所示:

image.png

若要导出包含资源文件的包,使用 mylibrary-release.aar 即可。

PS: 若只需要 *.aar 包,则只需无需配置 task makeJar,只要在项目选择 Build -> Rebuild Project,之后即可找到 release.aar 包。

5 导入包

得到 *.jar*.aar 后,若要在其他项目中引入该包,则需先复制该包(这里以 *.aar 包为例)到 app/libs 目录下(若无则创建一个),然后在 appbuild.gradle 中进行下述配置:

// 这是需要添加的
allprojects {
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
}

dependencies {
    ...

    // 添加这一行
    compile(name: 'mylibrary-1.0.0', ext: 'aar')
}

之后就能在项目中引用包里面的相关类和资源了:

此外,在 External Library 中也能看到我们引入的包,如图所示:

PS: 有点纳闷的是为什么跟其他的包格式不太一样,后面有个小横线……

点击进入包内,可以看到包里面相关的类和方法已经进行了混淆,如图所示:

Demo 链接:
打包:https://github.com/JiaoXR/Android-Demo/tree/master/RelativeLayoutTest
导入包:https://github.com/JiaoXR/Android-Demo/tree/master/LibraryTest

到此就算大体完成了。

参考链接:

  1. http://blog.csdn.net/lsyz0021/article/details/53107595
  2. https://stackoverflow.com/questions/21712714/how-to-make-a-jar-out-from-an-android-studio-project
  3. http://www.jianshu.com/p/0a3ce6e9ab85
  4. http://blog.csdn.net/guolin_blog/article/details/50451259

推荐阅读:

  1. Android安全攻防战,反编译与混淆技术完全解析(上)
  2. Android安全攻防战,反编译与混淆技术完全解析(下)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容