美文网首页
Android Studio 打包混淆的 SDK

Android Studio 打包混淆的 SDK

作者: 对歌当酒 | 来源:发表于2017-07-08 13: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安全攻防战,反编译与混淆技术完全解析(下)

    相关文章

      网友评论

          本文标题:Android Studio 打包混淆的 SDK

          本文链接:https://www.haomeiwen.com/subject/kavkhxtx.html