做Android开发的应该都知道,如果APK没有混淆打包,里面的代码反编译之后就跟明文没什么区别了,最近用proguard混淆用的比较多,这里记录下,以免以后忘了查看
1. 基本配置
eclipse下建立android工程,就会生成proguard.cfg和project.properties,在后面的文件追加proguard.config=proguard.cfg即可让前面的配置文件在export时生效。默认的那个文件有一些内容,这里给一个更通用点的。
##---------------Begin: proguard configuration common for all Android apps ---------- -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -keepattributes *Annotation* -renamesourcefileattribute SourceFile -keepattributes SourceFile,LineNumberTable # 以下两个命令配合让类的路径给删除了 -allowaccessmodification -repackageclasses '' # 记录生成的日志数据,在proguard目录下 -dump class_files.txt -printseeds seeds.txt -printusage unused.txt -printmapping mapping.txt # 异常都可以忽略就打开 #-dontwarn -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 -dontnote com.android.vending.licensing.ILicensingService -keepnames class * implements java.io.Serializable # Explicitly preserve all serialization members. The Serializable interface # is only a marker interface, so it wouldn't save them. -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(); } # Preserve all native method names and the names of their classes. -keepclasseswithmembernames class * { native <methods>; } -keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembernames class * { public <init>(android.content.Context, android.util.AttributeSet, int); } # Preserve static fields of inner classes of R classes that might be accessed # through introspection. -keepclassmembers class **.R$* { public static <fields>; } # Preserve the special static methods that are required in all enumeration classes. -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 如果你的工程是对外提供方法调用就打开 #-keep public class * { # public protected *; #} ##---------------End: proguard configuration common for all Android apps ----------
2. 解决export打包的报错
这个时候export提示“conversion to Dalvik format failed with error 1”错误,网上说法有好多种,最后我还是把proguard从4.4升级到4.8就解决了。官方地址是http://proguard.sourceforge.net。上面的配置文件参数可以在这里查阅。
升级办法很简单,就是把android sdk目录下的tool/proguard目录覆盖一下即可。
3. 打包出来的程序如何调试
一旦打包出来,就不能用eclipse的logcat去看了,这里可以用android sdk中ddms.bat的tool来看,一用就发现和logcat其实还是一个东西,就是多了个设备的选择。
在android上最好去下载一个logcat阅读器,这样在手机上运行崩溃了,不用连电脑也能查看日志了。可以再这里下载http://static.apk.hiapk.com/html/2012/03/438120.html。
4. 使用 gson 需要的配置
当Gson用到了泛型就会有报错,这个真给郁闷了半天,提示“Missing type parameter”。最后找到一个资料给了一个解决办法,参考:http://stackoverflow.com/questions/8129040/proguard-missing-type-parameter。
另外我又用到了JsonObject,提交的Object里面的members居然被改成了a。所以上面给的东西还不够,还要加上
# 用到自己拼接的JsonObject -keep class com.google.gson.JsonObject { *; }
我个人建议减少这些依赖包混淆带来的麻烦,干脆都全部保留不混淆。例如
-keep class com.badlogic.** { *; } -keep class * implements com.badlogic.gdx.utils.Json* -keep class com.google.** { *;
注意:就算这样配置了,在混淆打包的时候,gson依然可能会报错,如果还报错,请加上如下代码:
##---------------Begin: proguard configuration for Gson ----------# 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.** { *; }##---------------End: proguard configuration for Gson ----------
特别注意的是,在混淆的时候,如果用了反射,注解方面的,也一定要去掉,不然也会报错