安卓 代码混淆与打包

来源:互联网 发布:淘宝销售公司 编辑:程序博客网 时间:2024/05/16 07:21

代码混淆部分

gradle的配置

minifyEnabled trueproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'

proguard-rules.pro混淆配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
###-----------基本配置-不能被混淆的------------
-keep public class extends android.app.Activity
-keep public class extends android.app.Fragment
-keep public class extends android.app.Application
-keep public class extends android.app.Service
-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
 
#support.v4/v7包不混淆
-keep class android.support.** { *; }
-keep class android.support.v4.** { *; }
-keep public class extends android.support.v4.**
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v7.** { *; }
-keep public class extends android.support.v7.**
-keep interface android.support.v7.app.** { *; }
-dontwarn android.support.**    # 忽略警告
 
#保持注解继承类不混淆
-keep class extends java.lang.annotation.Annotation {*;}
#保持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;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
#保持枚举enum类不被混淆
-keepclassmembers enum * {
  public static **[] values();
 public static ** valueOf(java.lang.String);
}
#自定义组件不被混淆
-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*(...);
}
 
#不混淆资源类
-keepclassmembers class **.R$* {
    public static <fields>;
}
 
###-----------第三方jar包library混淆配置------------
#ormlite混淆配置
#-libraryjars libs/ormlite-android-5.0.jar
#-libraryjars libs/ormlite-core-5.0.jar
-dontwarn com.j256.ormlite.**
-keep class com.j256.ormlite.** { *;}
-keep class com.envy15.cherry.base.orm.** { *;}
#json-lib混淆配置
#-libraryjars libs/json-lib-2.4-jdk15.jar
-dontwarn net.sf.json.**
-keep class net.sf.json.** { *;}
#json-lib关联包
#-libraryjars libs/commons-beanutils-1.8.3.jar
-dontwarn org.apache.commons.**
-keep class org.apache.commons.** { *;}
#universalimageloader图片加载框架不混淆
-keep class com.nostra13.universalimageloader.** { *; }
-dontwarn com.nostra13.universalimageloader.**
#Gson相关的不混淆配置
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.google.gson.** { *; }
-dontwarn com.google.gson.**
-keep class com.envy15.cherry.fragment.crossover.model.** { *; }
-dontwarn com.envy15.cherry.fragment.crossover.model.**
-keep class com.envy15.cherry.fragment.discover.model.** { *; }
-dontwarn com.envy15.cherry.fragment.discover.model.**
-keep class com.envy15.cherry.fragment.local.model.** { *; }
-dontwarn com.envy15.cherry.fragment.local.model.**
-keep class com.envy15.cherry.fragment.setting.model.** { *; }
-dontwarn com.envy15.cherry.fragment.setting.model.**
#prt-lib下拉刷新框架不混淆
-keep class in.srain.cube.views.ptr.** { *; }
-dontwarn in.srain.cube.views.ptr.**
#PullToRefreshLibrary下拉刷新框架不混淆
-keep class com.handmark.pulltorefresh.library.** { *; }
-dontwarn com.handmark.pulltorefresh.library.**
 
#参考:
#  http://blog.csdn.net/zuiwuyuan/article/details/48552701
#  http://blog.csdn.net/fengyuzhengfan/article/details/43876197
#  http://blog.isming.me/2014/05/31/use-proguard/
#  http://hanhailong.com/2015/12/28/Android%E8%BF%9B%E9%98%B6%E4%B9%8BProGuard%E4%BB%A3%E7%A0%81%E6%B7%B7%E6%B7%86/
# 关于混淆的思考:
#  https://www.zhihu.com/question/37446729
# 扩展:资源文件混淆
#  http://blog.csdn.net/Fancy_xty/article/details/51202866
#代码混淆规则
# 指定代码的压缩级别
#-optimizationpasses 5
# 是否使用大小写混合
#-dontusemixedcaseclassnames
# 是否混淆第三方jar
#-dontskipnonpubliclibraryclasses
# 混淆时是否做预校验
#-dontpreverify
# 混淆时是否记录日志
#-verbose
# 混淆时所采用的算法
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
 
#-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.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              # 保持哪些类不被混淆
 
#-keepclasseswithmembernames class * {                                           # 保持 native 方法不被混淆
#    native <methods>;
#}
#
#-keepclasseswithmembers class * {                                               # 保持自定义控件类不被混淆
#    public <init>(android.content.Context, android.util.AttributeSet);
#}
#
#-keepclasseswithmembers class * {
#    public <init>(android.content.Context, android.util.AttributeSet, int);     # 保持自定义控件类不被混淆
#}
#
#-keepclassmembers class extends android.app.Activity {                        # 保持自定义控件类不被混淆
#   public void *(android.view.View);
#}
#
#-keepclassmembers enum * {                                                      # 保持枚举 enum 类不被混淆
#    public static **[] values();
#    public static ** valueOf(java.lang.String);
#}
#
#-keep class implements android.os.Parcelable {                                # 保持 Parcelable 不被混淆
#  public static final android.os.Parcelable$Creator *;
#}
 
#-keep class MyClass;                                                            # 保持自己定义的类不被混淆

 

打包发布部分

S1.使用默认方式打包签名APK

AndroidStudio选择Build => Generate Signed APK

总体步骤流程如下:

详细操作步骤:

S2. 多渠道打包APK

属性配置

productFlavors

    productFlavors {

        aVer {

            resValue("string","strKey","myKey")

            applicationId "com.simple.pkg.debug"

        }

        bVer {

            applicationId "com.simple.pkg.beta"

        }

        cVer {

            applicationId "com.simple.pkg.res"

        }

    }

signingConfigs

    signingConfigs {

        release {

            storeFile file('E:/XXX/app.jks') // 签名证书文件

            storePassword 'you password' // 证书密码

            keyAlias 'test'

            keyPassword 'you password '

        }

    }

buildTypes

    buildTypes {

        mbeta {

            signingConfig android.signingConfigs.release

            minifyEnabled false

        }

    }

 

S3.gradle打包自动化-定制apk文件名

gradle属性及变量定义的几种方式

变量定义

方式1(for gradle)

工程目录下gradle.properties定义属性:appName = MyAppName

App目录下build.gradle读取自定义属性:project.appName

方式2(for java)

App目录下build.gradle定义属性:

    productFlavors {

        aVer {

            // gradle定义全局变量方式2-代码使用

            buildConfigField "int", "varInt", "0"

            buildConfigField "String", "varString", '"abc"'

        }

}

Java代码读取属性:BuildConfig.varInt;BuildConfig.varString;

方式3(for java)

App目录下build.gradle定义属性:

    productFlavors {

        aVer {

            resValue("string","strKey","myKey")

        }

}

ava代码读取属性:context.getString(R.string.strKey);

方式4

App目录下build.gradle定义属性:

def flavorName = "undefine"

def indexFlavor(String str) {

    return str.substring(0,str.length())

}

Ref:

     android studio gradle 多版本多apk打包(打包系列教程之五)

     Gradle 自定义构建全局变量

     android studio 自定义gradle变量

 

定制apk文件名

变量定义

自定义生成APK文件名

applicationVariants.all { variant ->

variant.outputs.each { output ->

def outputFile = output.outputFile

         // appName + version + createTime + svnVersion + flavor + buildType

         def fileName = "fileName.apk"

         output.outputFile = new File(outputFile.parent, fileName)

       }

    }

获取相关属性

AppName:自定义方式或getName()

Version:版本, defaultConfig.versionName

CreateTime:创建时间,new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))

SvnVersion :SVN提交版本号
Flavor :编译渠道版本

BuildType:debug/beta/release版本

def fileName = "${project.appName}_v${defaultConfig.versionName}_${releaseTime()}_" +

                            "s${getSvnRevision()}_${indexFlavor(productFlavors.name)}_${getName()}.apk"

 

 

Ref:

     Android Gradle实用技巧——APK文件名中加上SVN版本号,日期等

     Android 使用Gradle打包APP名称和版本号

 

参考问题:

     buildTypes中加上signingConfig sigingConfigs.release运行就报错

build.gradle多渠道打包完整示例

复制代码
// app/build.gradle文件import org.tmatesoft.svn.core.wc.* // for svn versionapply plugin: 'com.android.application'def releaseTime() {    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))}def indexFlavor(String str) {    return str.substring(0,str.length())}def getSvnRevision() { // for svn    ISVNOptions options = SVNWCUtil.createDefaultOptions(true);    SVNClientManager clientManager = SVNClientManager.newInstance(options);    SVNStatusClient statusClient = clientManager.getStatusClient();    SVNStatus status = statusClient.doStatus(projectDir, false);    SVNRevision revision = status.getCommittedRevision();    return revision.getNumber();}android {    signingConfigs {    }    compileSdkVersion 25    buildToolsVersion "25.0.2"    defaultConfig {        applicationId "com.simple.res"        minSdkVersion 15        targetSdkVersion 21        versionCode 1        versionName "1.0"        multiDexEnabled true    // dex突破65535的限制    }    productFlavors {        aVer {            // gradle定义全局变量方式2-代码使用            buildConfigField "int", "varInt", "0"            buildConfigField "String", "varString", '"abc"'            //            resValue("string","strKey","myKey")            applicationId "com.simple.res.debug"        }        bVer {            applicationId "com.simple.res.beta"        }    }    signingConfigs {        release {            storeFile file('E:/XXX/App.jks')            storePassword 'you password'            keyAlias 'TEST'            keyPassword 'you password'        }    }    buildTypes {        debug {            minifyEnabled false        }        mbeta {            signingConfig android.signingConfigs.release            minifyEnabled false        }        release {            signingConfig android.signingConfigs.release            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'            minifyEnabled true            shrinkResources true            // 指定APK文件名            applicationVariants.all { variant ->                variant.outputs.each { output ->                    def outputFile = output.outputFile                    // appName + version + createTime + svnVersion + flavor + buildType                    def fileName = "${project.appName}_v${defaultConfig.versionName}_${releaseTime()}_" + "s${getSvnRevision()}_${indexFlavor(productFlavors.name)}_${getName()}.apk"                    output.outputFile = new File(outputFile.parent, fileName)                }            }        }    }}// project/build.gradle文件// 添加classpath group: 'org.tmatesoft.svnkit', name: 'svnkit', version: '1.8.11'支持获取// SVN提交版本号buildscript {    repositories {        jcenter()    }    dependencies {        classpath 'com.android.tools.build:gradle:2.2.3'        classpath group: 'org.tmatesoft.svnkit', name: 'svnkit', version: '1.8.11'}// project/build.gradle文件appName = NewApp
复制代码

 

1
2
3
4
* 崩溃日志记录
* 参考:
*  http://blog.csdn.net/u012333411/artile/details/49019415
*  http://blog.csdn.net/wangyuexing_blog/article/details/39009069
原创粉丝点击