为了防止代码被反编译,一般在签名导出前需要对代码进行混淆。最近发现自己的一个项目工程在代码混淆后,使用中出现了异常。以下是自己这几天在解决代码混淆以及引入第三方jar包导致混淆出现的问题处理的一些心得:
1.需要做混淆保护的内容:
(1.一般四大组件都会默认不被混淆
(2.自定义组件的类也要设置为不被混淆,否则找不到控件,例如:
1
2
3
|
-keep
public
class
rongqin.musicplayer.view.LrcView
-keep
public
class
com.viewpagerindicator.TitlePageIndicator
-keep
public
class
com.viewpagerindicator.LinePageIndicator
|
(3.被调用的第三方jar包的类等
2.找到混淆后编译异常问题所在的类
代码混淆后,类名就都被改变了。以下是自己摸索的一种比较笨的快速确认异常类的方法。
(1 首先根据异常信息,可以知道异常出现在 com.a.a.c.a这个文件夹里
这些类文件都在反编译后的classes.dex.dex2jar.jar文件里。
(2 将eclipse的项目视图切换为package presentation -> Hierarchical,切换后就可以看到工程的目录结构了。
(3 然后就可以根据比照大概的目录结构去找到对应的类了。
比如com.a.a.c.a这个类,自己的工程包名都是rongqin,com包是导入的第三方jar包的包名,根据com.a.a目录下有abcd四个文件夹加上一堆class,比照后就可以发现是gson这个jar包导致的问题。需要在proguard-project.txt中对gson类进行代码混淆保护。
找到文件夹后,如果目录里包含多个class文件,则还需要确定混淆后的class对应于哪个类。这时可以通过项目里的proguard目录下的mapping文件去查找每个class的混淆对应关系,从而确认到出异常的class。
3.对gson类防代码混淆的处理
使用gson类需要在proguard-project对gson类进行代码混淆的保护,防止被混淆。可以直接在proguard-project中加上下面的语句:
1
2
3
4
5
6
7
8
9
10
|
##---------------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也要进行防混淆保护。例如:
1
2
3
4
5
6
7
8
|
-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好了。