webview 中js交互 代码混淆后失效
*一般情况下js交互,代码混淆的时候需要配置规则,以下是通用的混淆规则
#保留annotation, 例如 @JavascriptInterface 等 annotation
-keepattributes *Annotation*
#保留跟 javascript相关的属性
-keepattributes JavascriptInterface
#保留JavascriptInterface中的方法
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
#这个根据自己的project来设置,这个类用来与js交互,所以这个类中的 字段 ,方法, 等尽量保持
-keepclassmembers public class com.packgename.custom.WVJBWebViewClient{
<fields>;
<methods>;
public *;
private *;
}
通过设置这些通用的规则之后,发现一些js调用还是出现了问题。最终根据 log 日志,以及mapping文件的查看,找出了原因。
先部署一个没有被 obfuscate 过的apk,然后查看 log 日志。
这个是正常的日志
E/batman: messageJson = {"callbackId":"objc_cb_1","data":"A string sent from android to JS"}
I/WVJB: SEND: {"callbackId":"objc_cb_1","data":"A string sent from android to JS"}
I/WVJB: RCVD: {"data":{"imgUrl":"*********************************","title":"*********************************","desc":"*********************************","link":"*********************************"}}
I/web: {"imgUrl":"*********************************","title":"*********************************","desc":"*********************************","link":"*********************************"}
I/WVJB: RCVD: {"responseData":{"imgUrl":"*********************************","title":"*********************************","desc":"*********************************","link":"*********************************"},"responseId":"objc_cb_1"}
这个是不正常的日志
E/batman: messageJson = {"a":"A string sent from android to JS","b":"objc_cb_1"}
I/WVJB: SEND: {"a":"A string sent from android to JS","b":"objc_cb_1"}
I/WVJB: RCVD: {"data":{"imgUrl":"*********************************","title":"*********************************","desc":"*********************************","link":"*********************************"}}
I/web: {"imgUrl":"*********************************","title":"*********************************","desc":"*********************************","link":"*********************************"}
发现 发送的messageJson中的字段已经被混淆了。
最终找到了内部类
private class WVJBMessage {
Object data = null;
String callbackId = null;
String handlerName = null;
String responseId = null;
Object responseData = null;
}
发现这个类,可能被混淆了。
然后去mapping文件中查看,查找关键字,发现WVJBMessage这个类中的字段果然被混淆了。
com.packgename.WVJBWebViewClient$WVJBHandler -> com.packgename.WVJBWebViewClient$WVJBHandler:
void request(java.lang.Object,com.ushopal.catwoman.custom.WVJBWebViewClient$WVJBResponseCallback) -> request
com.packgename.custom.WVJBWebViewClient$WVJBMessage -> cvy:
java.lang.Object data -> a
java.lang.String callbackId -> b
java.lang.String handlerName -> c
java.lang.String responseId -> d
java.lang.Object responseData -> e
com.ushopal.catwoman.custom.WVJBWebViewClient this$0 -> f
然后在proguard文件中加上规则
#这个类 必须保留,这个类在WVJBWebViewClient中传递数据,如果被混淆 会导致一些callback无法调用
-keep class com.packgename.custom.WVJBWebViewClient$WVJBMessage
#类中成员的变量名也不能混淆,这些变量名被作为json中的字段,不能改变。
-keepclassmembers class com.packgename.custom.WVJBWebViewClient$WVJBMessage{
<fields>;
}
加上规则之后的mapping文件
com.packgename.custom.WVJBWebViewClient$WVJBHandler -> com.packgename.custom.WVJBWebViewClient$WVJBHandler:
void request(java.lang.Object,com.ushopal.catwoman.custom.WVJBWebViewClient$WVJBResponseCallback) -> request
com.packgename.custom.WVJBWebViewClient$WVJBMessage -> com.packgename.custom.WVJBWebViewClient$WVJBMessage:
java.lang.Object data -> data
java.lang.String callbackId -> callbackId
java.lang.String handlerName -> handlerName
java.lang.String responseId -> responseId
java.lang.Object responseData -> responseData
可以看到这些字段都被保护下来了。
最终解决了问题。
总结:webview中的js交互混淆时,注意事项
- 混淆规则加入 js公用的规则
- 并且找出与js交互有关的bean类,进行保护
- 混淆规则所匹配的类,必须加入该类的 全部路径
- 对于内部类,应该使用 $ 符号,而不是用 .
- 对于混淆出现的问题,可以通过log和mapping文件进行追踪。