Android代码混淆一直以来是一件让人特别头疼的事,我也在网上或者别人的博客里参考了很多,大体上的思路是一样的。下面我就写一下我自己在写代码混淆时的步骤和遇到的一些问题。仅供参考!
1.
首先确保你创建的安卓程序中存在这两个文件,如果没有也不要着急,从别人的程序中拷贝一下这两个文件放到你的程序中就行啦~~~
2.文件project.properties中把#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt这句话中的#符号去掉。
3.接下来是编写proguard-project.tex中的代码,这一步是最重要的。首先,你的程序中有第三方的类库,有些类库是不能混淆的。当你在调用这些类库时,官网上应该都有介绍
语法
<span style="font-size:14px;">-basedirectory {directoryname} 指定基础目录为以后相对的档案名称 -injars {class_path} 指定要处理的应用程序jar,war,ear和目录 -outjars {class_path} 指定处理完后要输出的jar,war,ear和目录的名称 -libraryjars {classpath} 指定要处理的应用程序jar,war,ear和目录所需要的程序库文件 -dontskipnonpubliclibraryclasses 指定不去忽略非公共的库类。 -dontskipnonpubliclibraryclassmembers 指定不去忽略包可见的库类的成员。 保留选项 -keep {Modifier} {class_specification} 保护指定的类文件和类的成员 -keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好 -keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。 -keepnames {class_specification} 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames {class_specification} 保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclasseswithmembernames {class_specification} 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -printseeds {filename} 列出类和类的成员-keep选项的清单,标准输出到给定的文件 压缩 -dontshrink 不压缩输入的类文件 -printusage {filename} -whyareyoukeeping {class_specification} 优化 -dontoptimize 不优化输入的类文件 -assumenosideeffects {class_specification} 优化时假设指定的方法,没有任何副作用 -allowaccessmodification 优化时允许访问并修改有修饰符的类和类的成员 混淆 -dontobfuscate 不混淆输入的类文件 -printmapping {filename} -applymapping {filename} 重用映射增加混淆 -obfuscationdictionary {filename} 使用给定文件中的关键字作为要混淆方法的名称 -overloadaggressively 混淆时应用侵入式重载 -useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆 -flattenpackagehierarchy {package_name} 重新包装所有重命名的包并放在给定的单一包中 -repackageclass {package_name} 重新包装所有重命名的类文件中放在给定的单一包中 -dontusemixedcaseclassnames 混淆时不会产生形形色色的类名 -keepattributes {attribute_name,...} 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -renamesourcefileattribute {string} 设置源文件中给定的字符串常量 </span></span>
-optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -libraryjars libs/alipaySDK-20150610.jar -dontwarn com.alipay.** -dontwarn com.ta.utdid2.** -dontwarn com.ut.device.** -keep class com.alipay.** { *; } -keep class com.ta.utdid2.** { *; } -keep class com.ut.device.** { *; } -libraryjars libs/android-async-http-1.4.8.jar -dontwarn com.loopj.android.http.** -keep class com.loopj.android.http.** { *; } -libraryjars libs/android-support-v4.jar -dontwarn android.support.v4.** -keep class android.support.v4.** { *; } -keep interface android.support.v4.** { *; } -keep public class * extends android.support.v4.** -keep public class * extends android.app.Fragment -libraryjars libs/jg_filter_sdk_1.1.jar -libraryjars libs/libammsdk.jar -dontwarn com.tencent.** -keep class com.tencent.** { *; } -keep class com.tencent.wxop.** { *; } -libraryjars libs/mid-sdk-2.20.jar -libraryjars libs/mta-android-stat-sdk-2.1.0_20160111.jar -keep class com.tencent.stat.** {* ;} -keep class com.tencent.mid.** {* ;} -libraryjars libs/wup-1.0.0-SNAPSHOT.jar -libraryjars libs/Xg_sdk_v2.38_20150616_1057.jar -keep class com.tencent.android.tpush.** {* ;} -keep class com.tencent.mid.** {* ;} -libraryjars libs/armeabi/libtpnsSecurity.so -libraryjars libs/armeabi/libtpnsWatchdog.so -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(); } -keepclassmembers class com.shinewonder.shinecloudapp.** {*;} -keepclassmembers class com.shinewonder.shinecloudapp.wxapi.**{*;} -keep class android.** {*; } -keep public class * extends android.view -keep public class * extends android.app.Fragment -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 -keep class com.tencent.mm.sdk.openapi.WXMediaMessage {*;} -keep class com.tencent.mm.sdk.openapi.** implements com.tencent.mm.sdk.openapi.WXMediaMessage$IMediaObject {*; } -keep public class * extends LinearLayout -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*(...); } -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 * {#枚举类不能去混淆 public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { #aidl文件不能去混淆 public static final android.os.Parcelable$Creator *; } -keepclassmembers class **.R$* {*;}#不混淆R文件里的资源 -keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); } -keep class com.test.model.response.** {*;}#反射类不能进行混淆编译</span></span>
demo只是我自己的程序的混淆,不全面,你自己的程序还有哪些不需要混淆,自己再写进去就可以了。
4.最后一步:签名打包。
完成这四步,你的代码混淆就算完成了,接下来检验一下你的混淆是否成功了
我测试用到的这个工具ApkIDE.exe。ApkIDE是反编译你的apk的,
操作特别简单,首先把你的打开ApkIDE.exe,把你混淆好的apk拖拽到里面就能进行反编译了
编译好的程序中的smali就是class,你的一些class被一些a,b,c......字母代替了,证明你的反编译成功了。恭喜你!
我的代码混淆就介绍这么多了
温馨提示:
代码混淆是一个特别麻烦的工作,中间会出现好多的错误,导致你混淆后的apk根本就无法运行,这时候你需要用到ddms.bat这个工具进行调试。