为了防止代码被反编译,一般在签名导出前需要对代码进行混淆。最近发现自己的一个项目工程在代码混淆后,使用中出现了异常。以下是自己这几天在解决代码混淆以及引入第三方jar包导致混淆出现的问题处理的一些心得:


1.需要做混淆保护的内容:

(1.一般四大组件都会默认不被混淆

(2.自定义组件的类也要设置为不被混淆,否则找不到控件,例如:

-keep public class rongqin.musicplayer.view.LrcView
-keep public class com.viewpagerindicator.TitlePageIndicator
-keep public class com.viewpagerindicator.LinePageIndicator

(3.被调用的第三方jar包的类等


2.找到混淆后编译异常问题所在的类

Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法_第1张图片

  代码混淆后,类名就都被改变了。以下是自己摸索的一种比较笨的快速确认异常类的方法。


(1 首先根据异常信息,可以知道异常出现在 com.a.a.c.a这个文件夹里

   这些类文件都在反编译后的classes.dex.dex2jar.jar文件里。

Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法_第2张图片



(2 将eclipse的项目视图切换为package presentation -> Hierarchical,切换后就可以看到工程的目录结构了。

Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法_第3张图片


(3 然后就可以根据比照大概的目录结构去找到对应的类了。

  比如com.a.a.c.a这个类,自己的工程包名都是rongqin,com包是导入的第三方jar包的包名,根据com.a.a目录下有abcd四个文件夹加上一堆class,比照后就可以发现是gson这个jar包导致的问题。需要在proguard-project.txt中对gson类进行代码混淆保护。

Android笔记:防反编译、代码混淆中,解决第三方jar包不被混淆的一些心得,及gson防混淆方法_第4张图片



  找到文件夹后,如果目录里包含多个class文件,则还需要确定混淆后的class对应于哪个类。这时可以通过项目里的proguard目录下的mapping文件去查找每个class的混淆对应关系,从而确认到出异常的class。



3.对gson类防代码混淆的处理

 使用gson类需要在proguard-project对gson类进行代码混淆的保护,防止被混淆。可以直接在proguard-project中加上下面的语句:

##---------------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
# 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 ----------


参考资料:http://stackoverflow.com/questions/8129040/proguard-missing-type-parameter


另外,因为使用gson类在解析json时,对应的类型key变量名需要与json文件里的一致,所有这部分的class也要进行防混淆保护。例如:

-keep public class rongqin.util.SongJson
-keep public class rongqin.util.SongJson.** { *; }
-keepclassmembers class rongqin.util.SongJson {
   public *;
}
-keepclasseswithmembernames class rongqin.util.SongJson {
public *;
}



至此,算是终于大功告成,不再弹出异常了。可能还有更有效的办法,希望高人赐教,多多交流。




其他笔记:

1.Eclipse打包Android项目时用到proguard.cfg后,出现的Warning:can't find referenced class问题的解决方案

找不到引用的这个类是第三方包里面的,很多时候我们只需要打乱自己的代码就行了,第三方包的代码就是否要打乱就不要管了。

我们可以使用
-dontwarn com.xx.bbb.**
-keep class com.xx.bbb.** { *;}

参数来保持第三方库中的类而不乱,-dontwarn和-keep 结合使用,意思是保持com.xx.bbb.**这个包里面的所有类和所有方法而不混淆,接着还叫ProGuard不要警告找不到com.xx.bbb.**这个包里面的类的相关引用。


2.如何通过代码风格实现更好的混淆效果


Proguard对一般用途来说足够了,但是也需要注意一些程序风格,增强proguard的效果:

1. 特定类的public函数不做实际的事情,只做简单处理后调用private函数。proguard对会对一些特定类的public函数不做混淆,以便被AndroidManifest.xml和各种layout引用。
2. 会被AndroidMinifest.xml和layout引用的类放在浅层的包中,需要隐藏的类放在较深处,以便proguard混淆包名带来好处。如果一个包中有需要不混淆的内容,则整个包名都不会被混淆。
3. 将函数根据功能分细切短也会有些益处。

如果隐藏代码的要求比较高,还是用native好了。