快捷搜索:  汽车  科技

android应用开发基础知识:Android开发小知识

android应用开发基础知识:Android开发小知识我们也可以单独为module配置混淆规则,比较推荐这种做法。每个module管理自己的混淆文件,当我们不依赖该module的时候,就不会发生第一种方法出现的问题了。2)各个module单独配置混淆规则(推荐) 混淆方法1)在app module中统一配置混淆规则 我们可以直接在app module中build.gradle文件配置所有module需要混淆的规则。这样,其他module中就无需开启混淆。但是并不推荐使用这种方法,当我们取消依赖某些module的时候,这样很容易造成混淆规则冗余,我们还需要删除掉该module相关的混淆配置,很麻烦。

Android Studio本身集成了ProGuard混淆工具,我们可以通过编辑build.gradle文件来开启混淆并且对代码进行压缩,对资源进行优化等。如下图

android应用开发基础知识:Android开发小知识(1)

下面是代码,可以直接复制

buildTypes { release { minifyEnabled true //开启混淆 zipAlignEnabled true //压缩优化 shrinkResources true //移出无用资源 proguardFiles getDefaultProguardFile('proguard-android.txt') 'proguard-rules.pro' //默认的混淆文件以及我们指定的混淆文件 } } 1 2 3 4 5 6 7 8 9 10

开启了混淆别忘去proguard-rules.pro文件编辑混淆规则,混淆规则网上也有很多,自行百度即可。

android应用开发基础知识:Android开发小知识(2)

如果你的项目只有一个app module,那么这样配置混淆就可以了。但是如果你的项目有好几个module,module之间还是相互依赖的,那么该怎么混淆呢?

混淆方法

1)在app module中统一配置混淆规则

我们可以直接在app module中build.gradle文件配置所有module需要混淆的规则。这样,其他module中就无需开启混淆。但是并不推荐使用这种方法,当我们取消依赖某些module的时候,这样很容易造成混淆规则冗余,我们还需要删除掉该module相关的混淆配置,很麻烦。

2)各个module单独配置混淆规则(推荐)

我们也可以单独为module配置混淆规则,比较推荐这种做法。每个module管理自己的混淆文件,当我们不依赖该module的时候,就不会发生第一种方法出现的问题了。

我们把app module称作为主模块,其依赖的其他module称作为子模块

如图所示。我的app模块是依赖了其他模块的,其他模块也有相互依赖的地方。

android应用开发基础知识:Android开发小知识(3)

网上很多关于子module的混淆配置是错误的,经过我的多次实践得出,主模块的混淆开关配置会直接影响到子模块,也就是说如果你的主模块开启的混淆,就算你的子模块关闭混淆开关,最终子模块还是会被混淆的。

其次

子模块混淆文件的指定是通过consumerProguardFiles这个属性来指定的,并不是proguardFiles 属性,而且我们无需配置其他的选项,只需要配置consumerProguardFiles属性就可以。该属性表示在打包的时候会自动寻找该module下我们指定的混淆文件对代码进行混淆。

如果我们发布出一些开源库去给别人用,想要对库代码进行混淆的话,也可以通过配置该属性来达到目的

android应用开发基础知识:Android开发小知识(4)

关于多模块混淆的小技巧

一般来说,在组件化开发的情况下,app module的代码是很少的,依赖的第三方库也是很少的。我们可以把通用的混淆规则放到app module中。 这样子module就无需配置通用混淆规则,只需要配置一些该module所需要的混淆规则即可。大大减少了混淆代码。

app module下的混淆规则

这里给出一个也是从网上找的基本的混淆模板。关于自己项目的实体类和依赖的第三方sdk需要自己添加混淆规则,一般开源库都会给出混淆规则,没有的话就要自己百度了

# #-------------------------------------------基本不用动区域---------------------------------------------- # # # -----------------------------基本 ----------------------------- # # 指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。) -optimizationpasses 5 # 混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名) -dontusemixedcaseclassnames # 指定不去忽略非公共的库类(不跳过library中的非public的类) -dontskipnonpubliclibraryclasses # 指定不去忽略包可见的库类的成员 -dontskipnonpubliclibraryclassmembers #不进行优化,建议使用此选项, -dontoptimize # 不进行预校验 Android不需要 可加快混淆速度。 -dontpreverify # 屏蔽警告 -ignorewarnings # 指定混淆是采用的算法,后面的参数是一个过滤器 # 这个过滤器是谷歌推荐的算法,一般不做更改 -optimizations !code/simplification/arithmetic !field/* !class/merging/* # 保护代码中的Annotation不被混淆 -keepattributes *Annotation* # 避免混淆泛型 这在JSON实体映射时非常重要 -keepattributes Signature # 抛出异常时保留代码行号 -keepattributes SourceFile LineNumberTable #优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。 # 比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。 # 虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。 #指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public 而在api中可能变成public -allowaccessmodification #当有优化和使用-repackageclasses时才适用。 #-repackageclasses com.test # 混淆时记录日志(打印混淆的详细信息) # 这句话能够使我们的项目混淆后产生映射文件 # 包含有类名->混淆后类名的映射关系 -verbose # # ----------------------------- 默认保留 ----------------------------- # #---------------------------------------------------- # 保持哪些类不被混淆 #继承Activity application service broadcastReceiver contentprovider....不进行混淆 -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.support.multidex.MultiDexApplication -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 * extends android.view.View -keep class android.support.** {*;}## 保留support下的所有类及其内部类 -keep public class com.google.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService #表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。 #---------------------------------------------------- # 保留继承的 -keep public class * extends android.support.v4.** -keep public class * extends android.support.v7.** -keep public class * extends android.support.annotation.** #表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致 -keepclasseswithmembernames class * { native <methods>; } #这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆 #表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性, #当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了 -keepclassmembers class * extends android.app.Activity{ public void *(android.view.View); } #表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } #表示不混淆任何一个View中的setXxx()和getXxx()方法, #因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。 -keep public class * extends android.view.View{ *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context android.util.AttributeSet); public <init>(android.content.Context android.util.AttributeSet int); } -keepclasseswithmembers class * { public <init>(android.content.Context android.util.AttributeSet); public <init>(android.content.Context android.util.AttributeSet int); } #表示不混淆Parcelable实现类中的CREATOR字段, #毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 这指定了继承Serizalizable的类的如下成员不被移除混淆 -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(); } # 保留R下面的资源 -keep class **.R$* { *; } #不混淆资源类下static的 -keepclassmembers class **.R$* { public static <fields>; } # 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 -keepclassmembers class * { void *(**On*Event); void *(**On*Listener); } # 保留我们自定义控件(继承自View)不被混淆 -keep public class * extends android.view.View{ *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context android.util.AttributeSet); public <init>(android.content.Context android.util.AttributeSet int); } # #----------------------------- WebView(项目中没有可以忽略) ----------------------------- # #webView需要进行特殊处理 -keepclassmembers class fqcn.of.javascript.interface.for.Webview { public *; } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView java.lang.String android.graphics.Bitmap); public boolean *(android.webkit.WebView java.lang.String); } -keepclassmembers class * extends android.webkit.WebViewClient { public void *(android.webkit.WebView jav.lang.String); } #在app中与HTML5的JavaScript的交互进行特殊处理 #我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理: -keepclassmembers class com.ljd.example.JSInterface { <methods>; } #(可选)避免Log打印输出 -assumenosideeffects class android.util.Log { public static *** v(...); public static *** d(...); public static *** i(...); public static *** w(...); } 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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

子module下的混淆配置 示例

只需要配置改module需要的混淆规则即可,注意我这里只是个示例,具体的混淆规则根据你的module来定。

android应用开发基础知识:Android开发小知识(5)

这样一来,我们就优雅的完成了多module下的混淆配置。

好了,就这些,希望能帮到你。觉得还行的话点个赞呦。

猜您喜欢: