背景:
使用OkHttp做网络请求,并且用到了持久化Cookie,app没有混淆一切正常,但是混淆之后,不能正常读取cookie了。
经过排查发现是序列化的cookie字符串不正确,自然而然的想到要keep住实现了Serializable接口的类,然后就找到了SerializableOkHttpCookies这个类,代码如下:
public class SerializableOkHttpCookies implements Serializable {
private transient final Cookie cookies;
private transient Cookie clientCookies;
public SerializableOkHttpCookies(Cookie cookies) {
this.cookies = cookies;
}
public Cookie getCookies() {
Cookie bestCookies = cookies;
if (clientCookies != null) {
bestCookies = clientCookies;
}
return bestCookies;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(cookies.name());
out.writeObject(cookies.value());
out.writeLong(cookies.expiresAt());
out.writeObject(cookies.domain());
out.writeObject(cookies.path());
out.writeBoolean(cookies.secure());
out.writeBoolean(cookies.httpOnly());
out.writeBoolean(cookies.hostOnly());
out.writeBoolean(cookies.persistent());
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
String name = (String) in.readObject();
String value = (String) in.readObject();
long expiresAt = in.readLong();
String domain = (String) in.readObject();
String path = (String) in.readObject();
boolean secure = in.readBoolean();
boolean httpOnly = in.readBoolean();
boolean hostOnly = in.readBoolean();
boolean persistent = in.readBoolean();
Cookie.Builder builder = new Cookie.Builder();
builder = builder.name(name);
builder = builder.value(value);
builder = builder.expiresAt(expiresAt);
builder = hostOnly ? builder.hostOnlyDomain(domain):builder.domain(domain);
builder = builder.path(path);
builder = secure ? builder.secure() : builder;
builder = httpOnly ? builder.httpOnly() : builder;
clientCookies =builder.build();
}
保存cookie信息,实际就是将这个类对象序列号,并且用SharedPreferences去存储,于是简单的认为只要在混淆配置文件里加一句:
-keep class * implements java.io.Serializable
然而,问题还是没有解决!!!
其实对于SerializableOkHttpCookies 这个类是充满疑问的:
1、transient 关键字有什么作用呢?
声明了transient 的成员变量不参与序列化了
2、private void writeObject()和private void readObject()这两个方法被声明private的,有什么用呢?
如果要简单序列化一个对象,只需要实现Serializable接口即可,但如果想要定制序列化内容,那就要实现writeObject()和readObject()这两个方法了,并且声明为private的。
综上,解决方法是在混淆配置文件里加上
-keep class * implements java.io.Serializable {*;}
OK,问题解决了!