I am getting a strange behavior, and I guess I'm more looking for an explanation than a solution (although solution is welcome as well!).
Here's the code:
PackageManager pm = context.getPackageManager();
List<PackageInfo> pkgList = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
if (pkgList == null)
return null;
for (PackageInfo pkgInfo : pkgList) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
// do some stuff, doesn't modify pkgInfo or appInfo or pkgList
}
And on some occasions, I am getting error logs with:
java.lang.ClassCastException: cannot be cast to android.content.pm.PackageInfo
reported for line:
for (PackageInfo pkgInfo : pkgList)
The odd part is that, normally, ClassCastException
usually look like (AFAIK):
java.lang.ClassCastException: foo.bar.ClassA cannot be cast to foo.bar.ClassB
However, the error I'm seeing is showing blank for the first part.
I decided to research a bit, and read something along the lines of it might happen if the function that's returning the list internally casted the wrong object list and returned it or something. So I looked:
ApplicationPackageManager.getInstalledPackages()
@SuppressWarnings("unchecked")
@Override
public List<PackageInfo> getInstalledPackages(int flags) {
try {
final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
PackageInfo lastItem = null;
ParceledListSlice<PackageInfo> slice;
do {
final String lastKey = lastItem != null ? lastItem.packageName : null;
slice = mPM.getInstalledPackages(flags, lastKey);
lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
} while (!slice.isLastSlice());
return packageInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
Ok, so the list that's being returned is populated from ParceledListSlice.populateList()...
ParceledListSlice.populateList()
public T populateList(List<T> list, Creator<T> creator) {
mParcel.setDataPosition(0);
T item = null;
for (int i = 0; i < mNumItems; i++) {
item = creator.createFromParcel(mParcel);
list.add(item);
}
mParcel.recycle();
mParcel = null;
return item;
}
So the item is being created from PackageInfo.CREATOR.createFromParcel()
...
And finally the creator.createFromParcel
of PackageInfo
public static final Parcelable.Creator<PackageInfo> CREATOR
= new Parcelable.Creator<PackageInfo>() {
public PackageInfo createFromParcel(Parcel source) {
return new PackageInfo(source);
}
public PackageInfo[] newArray(int size) {
return new PackageInfo[size];
}
};
So everything seems to be ok. It's creating a ParceledListSlice
of type PackageInfo
, and so in populateList
it's creating a PackageInfo
item and putting it into a List
of PackageInfo
, which is the returned list. All the types/classes seem fine to me.
So my questions,
- how would the above ClassCastException happen?
- Why would it show "blank" type for the error message?
- And what would be a possible solution?
I was thinking of just getting the list as a list of Object
and checking "instanceof
", but I don't think that's gonna work either because it'll probably end up saying
ClassCastException: cannot be cast into java.lang.Object" or something.
Any insights and explanations on how this could happen would be greatly appreciated.
- Is Dalvik/JVM simply messing up?
- Is the memory being corrupted?
I could only come up wild guesses =)
for loop
where you loop to the length ofpkgList
. This would tell you if some of the items in the list are of classPackageInfo
. – Graeme