Android ResolveInfo Parcelable not completely unparceled

147
December 20, 2017, at 03:18 AM

I'm stumbling on what I would have expected to be an easy task, that is writing a ResolveInfo object to a Parcel and then creating a ResolveInfo from this Parcel. Sadly it is not as my code crashes and throws a java.lang.IllegalStateException.

Here is my code

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!
}

Looking at the source code of the ResolveInfo class the exception is thrown when none of the ResolveInfo ActivityInfo, ServiceInfo or ProviderInfo attributes are present. I therefore added logs to check if these were missing.

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)}")
}

My original ResolveInfo object has an ActivityInfo but my copy doesn't. ActivityInfo implements Parcelable so I don't quite understand why it isn't written in the Parcel. According to the source of ResolveInfo it should be written in the parcel and read from it:

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;
}

Clue anyone as to why this nested Parcelable isn't unparceled properly? Am I missing useful flags I should use?

Thanks,

READ ALSO
How can I make all play-services libraries the same version to avoid a duplicate class error when trying to run the app on a physical device?

How can I make all play-services libraries the same version to avoid a duplicate class error when trying to run the app on a physical device?

How can I make all play-services libraries the same version to avoid a duplicate class error when trying to run the app on a physical device? In the external libraries i see version 1020 and 11

143
Delete Item form DB out of ListView

Delete Item form DB out of ListView

I scrolled through many questions, but i didn'tget it or just found unspecific answers

199
How to make an e-mail “sender” [on hold]

How to make an e-mail “sender” [on hold]

I have to develop and app, that's have a function, that is send and email to me, through a predetermined email address, that's not overwritteableHow can I do this?

133
connecting to kurento media server java tutorial via websocket

connecting to kurento media server java tutorial via websocket

I'm trying to connect to websocket from my Android app but I'm having a hard time establishing the connectionWhen I'm trying to connect from socket explorers it connect normally, but when I'm trying to establish connection from Android I get this message:

252