Android代码搅混的实践

Android代码混淆的实践

      做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://*.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  ----------


特别注意的是,在混淆的时候,如果用了反射,注解方面的,也一定要去掉,不然也会报错