zoukankan      html  css  js  c++  java
  • androidStudio 打包与混淆

    在gradle中通过makeJar打包

      不同模块的gradle都支持打包功能,application module的build.gradle中引入的是com.android.application插件来打包,而library module的build.gradle中引入的是com.android.library插件进行打包。

    一. 基本概念(Project 和 Task)

      Gradle中有两个基本的概念:project和task。每个Gradle的构建由一个project构成,它代表着需要被构建的组件或者构建的整个项目。每个project由一个或者多个task组成。task代表着Gradle构建过程中可执行的最小单元。例如当构建一个组件时,可能需要先编译、打包、然后再生成文档或者发布等,这其中的每个步骤都可以定义成一个task,gradle会创建一个脚本来执行这些task

    Task实例:

    在app目录的gradle中新建一个任务:

      task hello {
          doLast{
               println "hello world"
          }
     }

    通过 gradlew hello  就可以在终端运行这个 task

    “doLast” :  为定义的一个映射,意思为在这个task的最后运行。同样还可以在定义doFirst:在task的开始执行

    Task中的依赖: dependsOn      

    如果B.dependOn A ;     B的执行必须在A执行,在二:项目中在Task中打Jar包  代码中,

    dependsOn:['compileReleaseJavaWithJavac']  表示在编译完release的版本之后再执行该任务

    二:项目中在Task中打Jar包

       task makeJar(dependsOn:['compileReleaseJavaWithJavac'], type: Jar) {
            archiveName = 'AssistSDK.jar';
            delete 'build/libs/AssistSDK.jar'
            from('build/intermediates/classes/release')
            from(project.zipTree("libs/liteProtobuf.jar"));
            destinationDir = file('sbuild/lib')
            exclude('xxx/BuildConfig.class')
            exclude('xxx/BuildConfig$*.class')
            exclude('**/R.class')
            exclude('**/R$*.class')
            include('xxx/**/*.class')
    //      include('com/google/protobuf/**/*.class')
        }

    上述代码中  

    exclude('xxx/BuildConfig.class')
    exclude('xxx/BuildConfig$*.class')

    两行代码的目的是为了 去掉jar中的 buildconfig.class (记录的一些参数)

            exclude('**/R.class')
            exclude('**/R$*.class')

    这两行代码的效果目前还不是很清楚,

    将第三方库的依赖代码 包含到Jar包中,这样 在包含本Jar的时候就不用再去包含第三方的Jar

      from(project.zipTree("libs/liteProtobuf.jar"));

    最后在命令行窗口 输入命令:  gradlew makeJar

    三、在Task中打混淆的Jar包

       task proguardJar(dependsOn: ['makeJar'], type: proguard.gradle.ProGuardTask) {
            configuration 'proguard-rules.pro'
            String inJar = makeJar.archivePath.getAbsolutePath()
            //输入 jar
            injars inJar
            println "lixiang->>"+inJar
            //输出 jar 的位置和名称
            String outJar = inJar.substring(0, inJar.lastIndexOf(File.separator)) + "/proguard-${makeJar.archiveName}"
            outjars outJar
            println "lixiang->>"+outJar
            //设置不删除未引用的资源(类,方法等)
            dontshrink
        }

    混淆proguard-rules.pro文件与混淆规则

    # If your project uses WebView with JS, uncomment the following
    # and specify the fully qualified class name to the JavaScript interface
    # class:
    #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
    #   public *;
    #}
    
    # 指定代码的压缩级别
    -optimizationpasses 5
    # 是否使用大小写混合
    -dontusemixedcaseclassnames
    # 是否混淆第三方jar
    -dontskipnonpubliclibraryclasses
    -dontoptimize
    # 预校验
    -dontpreverify
    # 混淆时是否记录日志
    -verbose
    # 混淆时所采用的算法
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    # 保护注解
    #-keepattributes *Annotation*
    #避免混淆泛型 如果混淆报错建议关掉
    #-keepattributes Signature
    
    # 保持哪些类不被混淆
    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Application
    -keep public class * extends android.app.Service
    -keep public class * extends android.app.IntentService
    -keep public class * extends android.content.BroadcastReceiver
    -keep public class * extends android.content.ContentProvider
    -keep public class * extends android.app.backup.BackupAgentHelper
    -keep public class * extends android.preference.Preference
    -keep public class com.android.vending.licensing.ILicensingService
    
    -keep public class * extends android.support.v4.app.Fragment
    
    #忽略警告
    -ignorewarning
    
    ##记录生成的日志数据,gradle build时在本项目根目录输出##
    
    #apk 包内所有 class 的内部结构
    -dump class_files.txt
    #未混淆的类和成员
    -printseeds seeds.txt
    #列出从 apk 中删除的代码
    -printusage unused.txt
    #混淆前后的映射
    #-printmapping mapping.txt
    
    ########记录生成的日志数据,gradle build时 在本项目根目录输出-end######
    
    #####混淆保护自己项目的部分代码以及引用的第三方jar包library#######
    #-libraryjars libs/umeng-analytics-v5.2.4.jar
    
    #三星应用市场需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar
    #-libraryjars libs/sdk-v1.0.0.jar
    #-libraryjars libs/look-v1.0.1.jar
    
    #如果引用了v4或者v7包
    -dontwarn android.support.**
    -keep class android.support.** {*; }
    
    ####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####
    
    -keep public class * extends android.view.View {
        public <init>(android.content.Context);
        public <init>(android.content.Context, android.util.AttributeSet);
        public <init>(android.content.Context, android.util.AttributeSet, int);
        public void set*(...);
    }
    
    #保持 native 方法不被混淆
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    #保持自定义控件类不被混淆
    -keepclasseswithmembers class * {
        public <init>(android.content.Context);
    }
    
    -keepclasseswithmembernames class * {
        public <init>(android.content.Context, android.util.AttributeSet);
    }
    
    -keepclasseswithmembernames class * {
        public <init>(android.content.Context, android.util.AttributeSet, int);
    }
    
    #保持 Parcelable 不被混淆
    -keep class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator *;
    }
    
    #保持 Serializable 不被混淆
    -keepnames class * implements java.io.Serializable
    
    #保持 Serializable 不被混淆并且enum 类也不被混淆
    -keepclassmembers class * implements java.io.Serializable {
        static final long serialVersionUID;
        private static final java.io.ObjectStreamField[] serialPersistentFields;
        !static !transient <fields>;
        !private <fields>;
        !private <methods>;
        private void writeObject(java.io.ObjectOutputStream);
        private void readObject(java.io.ObjectInputStream);
        java.lang.Object writeReplace();
        java.lang.Object readResolve();
        public void set*(***);
        public *** get*();
    }
    
    #保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    -keepclassmembers class * {
        public void *ButtonClicked(android.view.View);
    }
    
    #不混淆资源类
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
    
    # Gson uses generic type information stored in a class file when working with fields. Proguard
    # removes such information by default, so configure it to keep all of it.
    -keepattributes Signature
    
    # For using GSON @Expose annotation
    -keepattributes *Annotation*
    
    # Gson specific classes
    -keep class sun.misc.Unsafe { *; }
    #-keep class com.google.gson.stream.** { *; }
    
    # Application classes that will be serialized/deserialized over Gson
    #-keep class com.google.gson.examples.android.model.** { *; }
    
    #第三方jar包
    -keep class com.nostra13.universalimageloader.** { *; }
    -keep class com.android.volley.** {*; }
    -keep class org.apache.http.** {*; }

    2,内嵌类(尤为注意)

    内嵌类经常会被混淆,结果在调用的时候为空就崩溃了,最好的解决方法就是把这个内嵌类拿出来,单独成为一个类。如果一定要内置,那么这个类就必须在混淆的时候保留,比如如下:

    # 保留内嵌类不被混淆
    -keep class com.example.xxx.MainActivity$* { *; }

    这个$符号就是用来分割内嵌类与其母体的标志。

    (实际遇到匿名内部类被混淆,调用时找不到接口。 通过把匿名内部类设置为 内部类,然后保留不混淆)

    四、 dependencies 中六种依赖

    Android Studio引用第三方库很方便,只需要一句代码就可以搞定,几种引用第三方库的方式,总结一下:

    方式:1:它就会自动把这个包下载下来,并且引用它。节省git空间,而且修改版本也很方便。

      compile 'com.android.support:support-v4:23.3.0'    // 实际使用中经常会用 xxxx:+    insteadof version number

    方式2:引用libs下所有jar包

      compile fileTree(dir: 'libs', include: ['*.jar'])

    方式3:引用一个jar

      compile files('libs/fastjson-1.1.53.android.jar')

    方式4:引用一个aar文件,注意并不能像 方式2 那样自动引用全部的aar,而需要对每个aar分别进行引用。

      compile(name: 'aar_file_name', ext: 'aar')

    方式5:引用库类型的项目

      compile project(':xxxsdk')

    方式6:仅仅在编译时使用,但最终不会被编译到apk或aar里

      provided files('libs/glide-3.7.0.jar')

    Compile

    compile是对所有的build type以及favlors都会参与编译并且打包到最终的apk文件中。

    Provided

    Provided是对所有的build type以及favlors只在编译时使用,类似eclipse中的external-libs,只参与编译,不打包到最终apk。

    APK

    只会打包到apk文件中,而不参与编译,所以不能再代码中直接调用jar中的类或方法,否则在编译时会报错

    Test compile

    Test compile 仅仅是针对单元测试代码的编译编译以及最终打包测试apk时有效,而对正常的debug或者release apk包不起作用。

    Debug compile

    Debug compile 仅仅针对debug模式的编译和最终的debug apk打包。

    Release compile

    Release compile 仅仅针对Release 模式的编译和最终的Release apk打包。

    查看依赖结构命令  ./gradlew -q app:dependencies

    gredle 命令说明:

    https://docs.gradle.org/current/userguide/command_line_interface.html#para:commandline_dependency_report

    混淆规则参考:

      http://blog.csdn.net/nature_day/article/details/51545849

      http://www.jianshu.com/p/158aa484da13

    打包

          http://unclechen.github.io/2015/10/25/Gradle%E5%AE%9E%E8%B7%B5%E4%B9%8B%E6%89%93%E5%8C%85jar+Log%E5%BC%80%E5%85%B3%E8%87%AA%E5%8A%A8%E5%85%B3%E9%97%AD/

  • 相关阅读:
    RabbitMQ系列2 RabbitMQ安装与基础入门
    RabbitMQ系列1 什么是MQ
    数据结构与算法系列1之数组介绍与动态数组实现
    数据结构与算法系列3之从内存角度分析数组与链表的区别
    Dubbo学习
    Can't locate Pod/Text.pm问题分析及解决
    “画饼”陷阱论
    自述
    结构光、立体视觉、ToF三种3D传感原理
    游侠郭解是如何被无脑粉坑死的?
  • 原文地址:https://www.cnblogs.com/NeilZhang/p/7128136.html
Copyright © 2011-2022 走看看