Android Studio 打包混淆的 SDK

2017-07-08  本文已影响3017人  对歌当酒

前段时间公司项目需要开发一个 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安全攻防战,反编译与混淆技术完全解析(下)
上一篇下一篇

猜你喜欢

热点阅读