且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Android代码混淆的实践

更新时间:2022-09-22 08:25:53

开发apk的时候当然要考虑保护好自己的代码,Android环境就提供了proguard来进行代码混淆,确实是一个非常有用的工具,但用起来也确实够折腾的。

1. 基本配置

   eclipse下建立android工程,就会生成proguard.cfg和project.properties,在后面的文件追加proguard.config=proguard.cfg即可让前面的配置文件在export时生效。默认的那个文件有一些内容,这里给一个更通用点的。


  1. ##---------------Begin: proguard configuration common for all Android apps ---------- 
  2. -optimizationpasses 5 
  3. -dontusemixedcaseclassnames 
  4. -dontskipnonpubliclibraryclasses 
  5. -dontskipnonpubliclibraryclassmembers 
  6. -dontpreverify 
  7. -verbose 
  8. -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 
  9. -keepattributes *Annotation* 
  10. -renamesourcefileattribute SourceFile 
  11. -keepattributes SourceFile,LineNumberTable 
  12.  
  13. # 以下两个命令配合让类的路径给删除了 
  14. -allowaccessmodification 
  15. -repackageclasses '' 
  16.  
  17. # 记录生成的日志数据,在proguard目录下 
  18. -dump class_files.txt  
  19. -printseeds seeds.txt  
  20. -printusage unused.txt  
  21. -printmapping mapping.txt  
  22.  
  23. # 异常都可以忽略就打开 
  24. #-dontwarn 
  25.  
  26. -keep public class * extends android.app.Activity 
  27. -keep public class * extends android.app.Application 
  28. -keep public class * extends android.app.Service 
  29. -keep public class * extends android.content.BroadcastReceiver 
  30. -keep public class * extends android.content.ContentProvider 
  31. -keep public class * extends android.app.backup.BackupAgentHelper 
  32. -keep public class * extends android.preference.Preference 
  33. -keep public class com.android.vending.licensing.ILicensingService 
  34. -dontnote com.android.vending.licensing.ILicensingService 
  35.  
  36.  
  37. -keepnames class * implements java.io.Serializable 
  38.  
  39. # Explicitly preserve all serialization members. The Serializable interface 
  40. # is only a marker interface, so it wouldn't save them. 
  41. -keepclassmembers class * implements java.io.Serializable { 
  42.     static final long serialVersionUID; 
  43.     private static final java.io.ObjectStreamField[] serialPersistentFields; 
  44.     private void writeObject(java.io.ObjectOutputStream); 
  45.     private void readObject(java.io.ObjectInputStream); 
  46.     java.lang.Object writeReplace(); 
  47.     java.lang.Object readResolve(); 
  48.  
  49. # Preserve all native method names and the names of their classes. 
  50. -keepclasseswithmembernames class * { 
  51.     native <methods>
  52.  
  53. -keepclasseswithmembernames class * { 
  54.     public <init>(android.content.Context, android.util.AttributeSet); 
  55.  
  56. -keepclasseswithmembernames class * { 
  57.     public <init>(android.content.Context, android.util.AttributeSet, int); 
  58.  
  59. # Preserve static fields of inner classes of R classes that might be accessed 
  60. # through introspection. 
  61. -keepclassmembers class **.R$* { 
  62.   public static <fields>
  63.  
  64. # Preserve the special static methods that are required in all enumeration classes. 
  65. -keepclassmembers enum * { 
  66.     public static **[] values(); 
  67.     public static ** valueOf(java.lang.String); 
  68.  
  69. -keep class * implements android.os.Parcelable { 
  70.   public static final android.os.Parcelable$Creator *; 
  71.  
  72. # 如果你的工程是对外提供方法调用就打开 
  73. #-keep public class * { 
  74. #    public protected *; 
  75. #} 
  76.  
  77. ##---------------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。所以上面给的东西还不够,还要加上


  1. # 用到自己拼接的JsonObject 
  2. -keep class com.google.gson.JsonObject { *; } 

    我个人建议减少这些依赖包混淆带来的麻烦,干脆都全部保留不混淆。例如


  1. -keep class com.badlogic.** { *; } 
  2. -keep class * implements com.badlogic.gdx.utils.Json* 
  3. -keep class com.google.** { *; } 

5. 使用libgdx需要的配置

    参考http://code.google.com/p/libgdx-users/wiki/Ant

6. 验证打包效果

    我是利用了apktool的反编译工具,把打包文件又解压了看了一下,如果包路径、类名、变量名、方法名这些变化和你期望一致,那就OK了。命令:


  1. apktool.bat d xxx.apk destdir 

 

    总结:这个东西用起来也不是很简单,特别是你程序用到的高级特性多,就更容易出问题。另外proguard的参数看起来确实也有点不好理解,打包过程慢,测试也比较浪费时间。东西虽好,但真不是那么容易上手。



本文转自passover 51CTO博客,原文链接:http://blog.51cto.com/passover/898470,如需转载请自行联系原作者