Android ResolveInfo Parcelable 未完全解包
Android ResolveInfo Parcelable not completely unparceled
我正在努力完成我原以为是一项简单的任务,即将 ResolveInfo 对象写入 Parcel,然后从该 Parcel 创建 ResolveInfo。可悲的是,这不是因为我的代码崩溃并抛出 java.lang.IllegalStateException.
这是我的代码
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}") // throws java.lang.IllegalStateException: Missing ComponentInfo!
}
查看 ResolveInfo class 的源代码,当存在 none ResolveInfo ActivityInfo、ServiceInfo 或 ProviderInfo 属性时会抛出异常。因此,我添加了日志以检查这些是否丢失。
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original activity info ${resolveInfo.activityInfo}")
Log.d(TAG,"original service info ${resolveInfo.serviceInfo}")
Log.d(TAG,"original provider info ${resolveInfo.providerInfo}")
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy activity info ${copy.activityInfo}")
Log.d(TAG,"copy service info ${copy.serviceInfo}")
Log.d(TAG,"copy provider info ${copy.providerInfo}")
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}")
}
我原来的 ResolveInfo 对象有一个 ActivityInfo 但我的副本没有。 ActivityInfo实现的是Parcelable所以不太明白为什么不写在Parcel中。根据ResolveInfo的来源,它应该写在包裹中并从中读取:
public void writeToParcel(Parcel dest, int parcelableFlags) {
if (activityInfo != null) {
dest.writeInt(1);
activityInfo.writeToParcel(dest, parcelableFlags);
} else if (serviceInfo != null) {
dest.writeInt(2);
serviceInfo.writeToParcel(dest, parcelableFlags);
} else if (providerInfo != null) {
dest.writeInt(3);
providerInfo.writeToParcel(dest, parcelableFlags);
} else {
dest.writeInt(0);
}
if (filter != null) {
dest.writeInt(1);
filter.writeToParcel(dest, parcelableFlags);
} else {
dest.writeInt(0);
}
dest.writeInt(priority);
dest.writeInt(preferredOrder);
dest.writeInt(match);
dest.writeInt(specificIndex);
dest.writeInt(labelRes);
TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
dest.writeInt(icon);
dest.writeString(resolvePackageName);
dest.writeInt(targetUserId);
dest.writeInt(system ? 1 : 0);
dest.writeInt(noResourceId ? 1 : 0);
dest.writeInt(iconResourceId);
dest.writeInt(handleAllWebDataURI ? 1 : 0);
dest.writeInt(isInstantAppAvailable ? 1 : 0);
}
private ResolveInfo(Parcel source) {
activityInfo = null;
serviceInfo = null;
providerInfo = null;
switch (source.readInt()) {
case 1:
activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
break;
case 2:
serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
break;
case 3:
providerInfo = ProviderInfo.CREATOR.createFromParcel(source);
break;
default:
Slog.w(TAG, "Missing ComponentInfo!");
break;
}
if (source.readInt() != 0) {
filter = IntentFilter.CREATOR.createFromParcel(source);
}
priority = source.readInt();
preferredOrder = source.readInt();
match = source.readInt();
specificIndex = source.readInt();
labelRes = source.readInt();
nonLocalizedLabel
= TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
icon = source.readInt();
resolvePackageName = source.readString();
targetUserId = source.readInt();
system = source.readInt() != 0;
noResourceId = source.readInt() != 0;
iconResourceId = source.readInt();
handleAllWebDataURI = source.readInt() != 0;
instantAppAvailable = isInstantAppAvailable = source.readInt() != 0;
}
想知道为什么这个嵌套的 Parcelable 没有正确解包吗?我是否缺少我应该使用的有用标志?
谢谢,
好的,所以我找到了解决问题的方法,它与 Parcelable Creator 方法无关,但与我使用 Parcel 的方式有关。在 Parcel 中完成写入后,您必须使用 0 作为参数值调用 setDataPosition。
我的代码如下:
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
p.setDataPosition(0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}") // no longer throws java.lang.IllegalStateException
}
我正在努力完成我原以为是一项简单的任务,即将 ResolveInfo 对象写入 Parcel,然后从该 Parcel 创建 ResolveInfo。可悲的是,这不是因为我的代码崩溃并抛出 java.lang.IllegalStateException.
这是我的代码
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}") // throws java.lang.IllegalStateException: Missing ComponentInfo!
}
查看 ResolveInfo class 的源代码,当存在 none ResolveInfo ActivityInfo、ServiceInfo 或 ProviderInfo 属性时会抛出异常。因此,我添加了日志以检查这些是否丢失。
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original activity info ${resolveInfo.activityInfo}")
Log.d(TAG,"original service info ${resolveInfo.serviceInfo}")
Log.d(TAG,"original provider info ${resolveInfo.providerInfo}")
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy activity info ${copy.activityInfo}")
Log.d(TAG,"copy service info ${copy.serviceInfo}")
Log.d(TAG,"copy provider info ${copy.providerInfo}")
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}")
}
我原来的 ResolveInfo 对象有一个 ActivityInfo 但我的副本没有。 ActivityInfo实现的是Parcelable所以不太明白为什么不写在Parcel中。根据ResolveInfo的来源,它应该写在包裹中并从中读取:
public void writeToParcel(Parcel dest, int parcelableFlags) {
if (activityInfo != null) {
dest.writeInt(1);
activityInfo.writeToParcel(dest, parcelableFlags);
} else if (serviceInfo != null) {
dest.writeInt(2);
serviceInfo.writeToParcel(dest, parcelableFlags);
} else if (providerInfo != null) {
dest.writeInt(3);
providerInfo.writeToParcel(dest, parcelableFlags);
} else {
dest.writeInt(0);
}
if (filter != null) {
dest.writeInt(1);
filter.writeToParcel(dest, parcelableFlags);
} else {
dest.writeInt(0);
}
dest.writeInt(priority);
dest.writeInt(preferredOrder);
dest.writeInt(match);
dest.writeInt(specificIndex);
dest.writeInt(labelRes);
TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
dest.writeInt(icon);
dest.writeString(resolvePackageName);
dest.writeInt(targetUserId);
dest.writeInt(system ? 1 : 0);
dest.writeInt(noResourceId ? 1 : 0);
dest.writeInt(iconResourceId);
dest.writeInt(handleAllWebDataURI ? 1 : 0);
dest.writeInt(isInstantAppAvailable ? 1 : 0);
}
private ResolveInfo(Parcel source) {
activityInfo = null;
serviceInfo = null;
providerInfo = null;
switch (source.readInt()) {
case 1:
activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
break;
case 2:
serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
break;
case 3:
providerInfo = ProviderInfo.CREATOR.createFromParcel(source);
break;
default:
Slog.w(TAG, "Missing ComponentInfo!");
break;
}
if (source.readInt() != 0) {
filter = IntentFilter.CREATOR.createFromParcel(source);
}
priority = source.readInt();
preferredOrder = source.readInt();
match = source.readInt();
specificIndex = source.readInt();
labelRes = source.readInt();
nonLocalizedLabel
= TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
icon = source.readInt();
resolvePackageName = source.readString();
targetUserId = source.readInt();
system = source.readInt() != 0;
noResourceId = source.readInt() != 0;
iconResourceId = source.readInt();
handleAllWebDataURI = source.readInt() != 0;
instantAppAvailable = isInstantAppAvailable = source.readInt() != 0;
}
想知道为什么这个嵌套的 Parcelable 没有正确解包吗?我是否缺少我应该使用的有用标志?
谢谢,
好的,所以我找到了解决问题的方法,它与 Parcelable Creator 方法无关,但与我使用 Parcel 的方式有关。在 Parcel 中完成写入后,您必须使用 0 作为参数值调用 setDataPosition。
我的代码如下:
fun failingFunction(resolveInfo:ResolveInfo){
Log.d(TAG,"original label ${resolveInfo.loadLabel(this.packageManager)}")
val p = Parcel.obtain()
resolveInfo.writeToParcel(p, 0)
p.setDataPosition(0)
val copy = ResolveInfo.CREATOR.createFromParcel(p)
Log.d(TAG,"copy label ${copy.loadLabel(this.packageManager)}") // no longer throws java.lang.IllegalStateException
}