Android ClassCastException con el tipo en blanco

Estoy obteniendo un comportamiento extraño, y supongo que estoy buscando más una explicación que una solución (aunque la solución es bienvenida también!).

Aquí está el código:

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 } 

Y en algunas ocasiones, estoy recibiendo registros de errores con:

Java.lang.ClassCastException: no se puede convertir en android.content.pm.PackageInfo

Informó para la línea:

 for (PackageInfo pkgInfo : pkgList) 

La parte extraña es que, normalmente, ClassCastException generalmente se parece a (AFAIK):

Java.lang.ClassCastException : foo.bar.ClassA no se puede convertir en foo.bar.ClassB

Sin embargo, el error que estoy viendo está mostrando en blanco para la primera parte.

Decidí investigar un poco, y leer algo a lo largo de las líneas de que podría suceder si la función que está devolviendo la lista interna lanzó la lista de objetos erróneos y lo devolvió o algo así. Así que miré:

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, por lo que la lista que se está devolviendo se rellena desde 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; } 

Así que el elemento se está creando desde PackageInfo.CREATOR.createFromParcel()

Y finalmente el creator.createFromParcel de 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]; } }; 

Así que todo parece estar bien. Está creando un ParceledListSlice del tipo PackageInfo , por lo que en populateList está creando un elemento PackageInfo y lo pone en una List de PackageInfo , que es la lista devuelta. Todos los tipos / clases me parecen bien.

Así que mis preguntas,

  1. ¿Cómo ocurriría la anterior ClassCastException?
  2. ¿Por qué mostraría el tipo "en blanco" para el mensaje de error?
  3. ¿Y cuál sería una posible solución?

Yo estaba pensando en obtener la lista como una lista de Object y comprobar " instanceof ", pero no creo que va a funcionar ya sea porque probablemente terminará diciendo

ClassCastException: no se puede convertir en java.lang.Object "o algo.

Cualquier idea y explicaciones sobre cómo esto podría suceder sería muy apreciada.

  1. ¿Está Dalvik / JVM simplemente estropeando?
  2. ¿Está dañada la memoria?

Yo sólo podía llegar a conjeturas salvajes =)

Si está seguro de obtener ClassCastException en esta línea exacta

 for (PackageInfo pkgInfo : pkgList) 

Cuando una razón está siguiendo – de alguna manera pkgList contiene un valor de no PackageInfo clase. Supongo que es NULL valor. ¿Por qué no se puede ver en el mensaje de error ClassCast, porque className para el objeto NULL es sólo una cadena vacía.

Ahora, cómo resolver este manual de uso para el bucle. for aech bucle de for aech utiliza for aech debajo de la capilla, así que usted no tiene control sobre el lanzamiento de la clase en cada iteración. Pero si usas código como este:

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

Usted será capaz de controlar el casting de clase.

Además puede capturar ClassCastException y simplemente omitir este paso de ciclo para el siguiente.

Esto parece ser un problema en el propio Android. He encontrado algunos informes de fallos contra Android que muestran comportamientos similares:

Problema 26644: ClassCastException y IncompatibleClassChangeError

Tema 36560: Excepción en (SensorManager.java:521)

También he visto el IncompatibleClassChangeError que se menciona en el problema 26644 también. Mi única suposición es que estas aparentemente imposibles excepciones / errores se deben a alguna extraña corrupción de memoria o dalvik / jvm problema. No parece que haya algo malo con el código en sí. Si alguien más tiene una mejor explicación, no dude en chip =)

  • ¿Desarrollar una aplicación Java que se ejecuta tanto en la web como en una aplicación para Android?
  • Ormlite configuración sin utilizar las actividades de base
  • ¿Cuándo usar un hilo o servicio en Android?
  • ¿Cómo mostrar diferentes diseños en recyclerView?
  • ¿Cómo animar setVisibility para un imagebutton en Android?
  • Enviando cadena UTF-8 usando HttpURLConnection
  • Android FFmpegMediaPlayer Error (0, 0) mientras se reproduce?
  • ¿De dónde viene Enum.values ​​()?
  • String.equals () siempre devuelve true
  • definición de la función de inicialización de clase en java
  • Cómo convertir de un ArrayList de matrices a una matriz de matrices
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.