您的位置:首页 > 编程语言

google gson 使用proguard混淆代码注意事项

2015-07-14 23:41 405 查看
这里不介绍怎样开启代码混淆功能。具体方法可以参照:
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 {*;}





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: