我的项目与多个proguard文件相关联。如果我查看所有proguard文件,这里的规则处理Parcelable
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
}
-keep class * implements android.os.Parcelable {
*;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
我有以下类文件,这是在proguard进程之前。
package org.yccheok.jstock.engine;
import android.os.Parcel;
import android.os.Parcelable;
/**
*
* @author yccheok
*/
public class Code implements Parcelable {
private Code(String code) {
this.code = code;
}
public static Code newInstance(String code) {
if (code == null) {
throw new java.lang.IllegalArgumentException("code cannot be null");
}
return new Code(code);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + code.hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Code)) {
return false;
}
return this.code.equals(((Code)o).code);
}
@Override
public String toString() {
return code;
}
////////////////////////////////////////////////////////////////////////////
// Handling Parcelable nicely.
public static final Parcelable.Creator<Code> CREATOR = new Parcelable.Creator<Code>() {
public Code createFromParcel(Parcel in) {
android.util.Log.i("CHEOK", "createFromParcel");
return new Code(in);
}
public Code[] newArray(int size) {
android.util.Log.i("CHEOK", "newArray");
return new Code[size];
}
};
private Code(Parcel in) {
code = in.readString();
android.util.Log.i("CHEOK", "Code parcel " + code);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(code);
}
// Handling Parcelable nicely.
////////////////////////////////////////////////////////////////////////////
private String code;
}
package org.yccheok.jstock.engine;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.util.Log;
public class Code
implements Parcelable
{
public static final Parcelable.Creator<Code> CREATOR = new Parcelable.Creator()
{
public Code a(Parcel paramAnonymousParcel)
{
Log.i("CHEOK", "createFromParcel");
return new Code(paramAnonymousParcel, null);
}
public Code[] a(int paramAnonymousInt)
{
Log.i("CHEOK", "newArray");
return new Code[paramAnonymousInt];
}
};
private String code;
private Code(Parcel paramParcel)
{
this.code = paramParcel.readString();
Log.i("CHEOK", "Code parcel " + this.code);
}
private Code(String paramString)
{
this.code = paramString;
}
public static Code newInstance(String paramString)
{
if (paramString == null)
throw new IllegalArgumentException("code cannot be null");
return new Code(paramString);
}
public int describeContents()
{
return 0;
}
public boolean equals(Object paramObject)
{
if (paramObject == this)
return true;
if (!(paramObject instanceof Code))
return false;
return this.code.equals(((Code)paramObject).code);
}
public int hashCode()
{
return 527 + this.code.hashCode();
}
public String toString()
{
return this.code;
}
public void writeToParcel(Parcel paramParcel, int paramInt)
{
paramParcel.writeString(this.code);
}
}
如您所见,CREATOR
createFromParcel(Parcel)
和newArray(int)
已重命名为a(Parcel)
和newArray(int)
我希望在像Bundle.putParcelable
这样的parceble过程中,事情会失败,因为OS系统不再能找到createFromParcel
。
然而,令我惊讶的是,以下代码行仍然执行而没有问题
Log.i("CHEOK", "createFromParcel");
我可以知道为什么会这样吗?我希望Android OS能够执行createFromParcel(Parcel)
。操作系统如何知道需要执行a(Parcel)
?
答案 0 :(得分:1)
我也很好奇。事实证明,编译器创建了一个指向混淆方法的合成方法。如果您使用apktool
来反转apk并深入挖掘smali代码,则可以看到这一点。
以下是实现Foo
的类Parcelable
的相关smali,并且被混淆为createFromParcel()
- &gt; a()
。
# The synthetic method definition
.method public synthetic createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
invoke-virtual {p0, p1}, Lcom/example/Foo$1;->a(Landroid/os/Parcel;)Lcom/example/Foo;
move-result-object v0
return-object v0
.end method
# The obfuscated method definition
.method public a(Landroid/os/Parcel;)Lcom/example/Foo;
new-instance v0, Lcom/example/Foo;
invoke-direct {v0, p1}, Lcom/example/Foo;-><init>(Landroid/os/Parcel;)V
return-object v0
.end method
这是堆栈跟踪,它显示Parcel
类调用合成方法,然后调用模糊方法。
at com.example.Foo$1.a(SourceFile:52)
at com.example.Foo$1.createFromParcel(SourceFile:49)
at android.os.Parcel.readParcelable(Parcel.java:2471)
at android.os.Parcel.readValue(Parcel.java:2365)
at android.os.Parcel.readListInternal(Parcel.java:2793)
at android.os.Parcel.readArrayList(Parcel.java:2036)
at android.os.Parcel.readValue(Parcel.java:2386)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2732)
at android.os.BaseBundle.unparcel(BaseBundle.java:269)
at android.os.BaseBundle.getString(BaseBundle.java:992)