google gson 使用proguard混淆代码注意事项
2015-07-14 23:41
465 查看
这里不介绍怎样开启代码混淆功能。具体方法可以参照:
http://developer.android.com/tools/help/proguard.html http://proguard.sourceforge.net/#manual/usage.html
主要介绍混淆使用 google gson的代码的时候需要注意的问题和解决方法。
在使用Android Studio 自带的Proguard去混淆代码的时候。代码混淆可以通过,但是运行的时候出现下面错误:
最后定位代码位置在于:
分析原因:
由于gson使用映射的方法找到SignResponseData.class中对应的成员变量名称,将json格式的的字段对应的值赋值给SignResponseData类中对应的成员变量。
但是由于经过proguard后 SignResponseData内部的成员变量名称发生了变化。已经无法找到json字段中对应的类成员变量。所以导致所有生成的SignResponseData成员变量值都为null 。
解决方法 1:
在proguard-rules.pro中加入下面规则。 对SignResponseData.java的所有private 对象不进行obfuscation。
解决方法2:
在SignResponseData.java中,将所有被gson使用的变量都加下面声明,这样gson就可以识别对应的变量。
如果要保留的类是内部类。可以使用下面声明:
http://developer.android.com/tools/help/proguard.html http://proguard.sourceforge.net/#manual/usage.html
主要介绍混淆使用 google gson的代码的时候需要注意的问题和解决方法。
在使用Android Studio 自带的Proguard去混淆代码的时候。代码混淆可以通过,但是运行的时候出现下面错误:
07-13 14:25:41.549 22817-22817/? E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.project.mocha_patient, PID: 22817 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference at com.project.mocha_patient.login.c.a(Unknown Source) at com.project.mocha_patient.network.p.a(Unknown Source) at com.project.mocha_patient.network.p.onPostExecute(Unknown Source) at android.os.AsyncTask.finish(AsyncTask.java:636) at android.os.AsyncTask.access$500(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
最后定位代码位置在于:
public void ServerResponse(HttpTaskResult ret) { SignResponseData obj = JsonUtils.objectFromJson (ret.getResponesMsg(), SignResponseData.class); if (obj == null){ Toast.makeText(LoginActivity.this, "Server replied the wrong data, please check.", Toast.LENGTH_SHORT).show(); return ; } if (!obj.getStatus().equals(MCSConstants.POST_SUCCESSFUL)){ //异常位置 Toast.makeText(LoginActivity.this, "Server Error: " + obj.getMessage(), Toast.LENGTH_SHORT).show(); return; } .... }调试代码可以显示obj为非null。但是内部成员都为 null
public final class JsonUtils { private static Gson sGson = new Gson(); public static String jsonStringFromObject(Object object) { return sGson.toJson(object); } public static <T> T objectFromJson(String json, Class<T> clz) { try { return sGson.fromJson(json, clz); }catch (Exception e){ e.printStackTrace(); } return null; } public static<T> T objectFromJson(InputStream in, Class<T> clz) { try { JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8")); T object = sGson.fromJson(reader, clz); reader.close(); return object; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } }SignResponseData.java
public final class SignResponseData { private String regType; private String token; private String message; private String status; ... }
分析原因:
由于gson使用映射的方法找到SignResponseData.class中对应的成员变量名称,将json格式的的字段对应的值赋值给SignResponseData类中对应的成员变量。
但是由于经过proguard后 SignResponseData内部的成员变量名称发生了变化。已经无法找到json字段中对应的类成员变量。所以导致所有生成的SignResponseData成员变量值都为null 。
解决方法 1:
在proguard-rules.pro中加入下面规则。 对SignResponseData.java的所有private 对象不进行obfuscation。
##---------------Begin: proguard configuration for Gson ---------- -keep public class com.google.gson.** -keep public class com.google.gson.** {public private protected *;} -keepattributes Signature -keepattributes *Annotation* -keep public class com.project.mocha_patient.login.SignResponseData { private *; } ##---------------End: proguard configuration for Gson ----------
解决方法2:
在SignResponseData.java中,将所有被gson使用的变量都加下面声明,这样gson就可以识别对应的变量。
@SerializedName("name")
public final class SignResponseData { @SerializedName("regType") private String regType; @SerializedName("token") private String token; @SerializedName("message") private String message; @SerializedName("status") private String status; ... }
如果要保留的类是内部类。可以使用下面声明:
-keep class com.project.mocha_patient.login.FindForgotInfoActivity$ForgetResponse {*;} -keep class com.project.mocha_patient.account_setting.ChangePasswordActivity$ChangePasswordResponse {*;}
相关文章推荐
- C# GetType和typeof的区别
- 浅析Java web程序之客户端和服务器端交互原理(转)
- 【C++】深度探索C++对象模型读书笔记--构造函数语义学(The Semantics of constructors)(四)
- Java正则表达式匹配模式[贪婪型、勉强型、占有型]
- laravel5.0 view层 解决本地服务器和远程服务器网站路径问题
- 一行代码,发送邮件
- java中this的含义和用法
- Python学习视频链接
- Struts2的国际化
- ASP.NET OAuth:access token的加密解密,client secret与refresh token的生成
- Lua5.2.3源码阅读(2)-Table
- iOS面试之C语言
- C++语言编程基础1
- Lua5.2.3源码阅读(3)-Table(ipairs,pairs)
- 探测法的哈希表的C++实现(最新修改)
- Python标准库05 存储对象 (pickle包,cPickle包)
- 【转载】用纯粹的C++编写COM组件
- 二叉树重建示意图
- java 流传输压缩包
- C#编程 井字游戏