hiB*_*Lee 8 java android exception classcastexception android-package-managers
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
}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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];
}
};
Run Code Online (Sandbox Code Playgroud)
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,
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.
I could only come up wild guesses =)
如果你确定你ClassCastException 正好在这条线上
for (PackageInfo pkgInfo : pkgList)
Run Code Online (Sandbox Code Playgroud)
当后面有一个原因时 - 某种程度上pkgList包含非类值PackageInfo。我认为这就是NULL价值。为什么你在 ClassCast 错误消息中看不到它,因为className对于 NULL 对象来说只是空字符串。
现在,如何解决这个问题 - 使用手动 for 循环。for each循环Iterator在幕后使用,因此您无法控制每次迭代的类转换。但如果您将使用这样的代码:
for (int i = 0; i < pkgList.length; i++) {
Object pkgInfoObj = pkgList.get(i);
if (pkgInfoObj instanceof PackageInfo) {
PackageInfo pkgInfo = (PackageInfo) pkgInfoObj;
ApplicationInfo appInfo = pkgInfo.applicationInfo;
// do some stuff, doesn't modify pkgInfo or appInfo or pkgList
}
}
Run Code Online (Sandbox Code Playgroud)
您将能够控制班级选角。
此外,您可以捕捉 ClassCastException并跳过此循环步骤到下一个循环步骤。