Je rencontre un blocage d'application sur mon CV en raison de l'exception Unmarshalling. J'ai vérifié que tous les sérialisables ont un constructeur sans paramètres et même vérifié tous les sérialisables à l'aide d'ObjectStream (enregistrer dans un fichier et charger à partir d'un fichier). Comment puis-je comprendre le type de classe réel pour l'offset parcellable qui cause une exception:
Parcel Android.os.Parcel@42209460: Unmarshalling unknown type code
2131165303 at offset 3748
at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2080)
at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2105)
at Android.app.ActivityThread.access$600(ActivityThread.Java:136)
at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1201)
at Android.os.Handler.dispatchMessage(Handler.Java:99)
at Android.os.Looper.loop(Looper.Java:137)
at Android.app.ActivityThread.main(ActivityThread.Java:4876)
at Java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:511)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:804)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:571)
at com.kdgdev.xtension.core.XtensionMain.main(XtensionMain.Java:91)
at dalvik.system.NativeStart.main(Native Method)
Caused by: Java.lang.RuntimeException: Parcel Android.os.Parcel@42209460: Unmarshalling unknown type code 2131165303
at offset 3748
at Android.os.Parcel.readValue(Parcel.Java:2032)
at Android.os.Parcel.readSparseArrayInternal(Parcel.Java:2255)
at Android.os.Parcel.readSparseArray(Parcel.Java:1687)
at Android.os.Parcel.readValue(Parcel.Java:2022)
at Android.os.Parcel.readMapInternal(Parcel.Java:2226)
at Android.os.Bundle.unparcel(Bundle.Java:223)
at Android.os.Bundle.getSparseParcelableArray(Bundle.Java:1232)
at com.Android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.Java:1690)
at Android.app.Activity.onRestoreInstanceState(Activity.Java:999)
at com.actionbarsherlock.app.SherlockFragmentActivity.onRestoreInstanceState(Unknown
Source)
at name.myname.Android.app.ui.MainActivity.onRestoreInstanceState(Unknown
Source)
at Android.app.Activity.performRestoreInstanceState(Activity.Java:971)
at Android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.Java:1130)
at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2058)
... 12 more
Les données sauvegardées sont constituées de Bundle
s et Serializable
s, qui ont toutes une belle apparence.
Je vais faire le prochain:
try {
// unmarshalling
} catch (Throwable t) {
// look offset
}
Comment puis-je comprendre quel type est réellement pour l'offset parcellaire?
C'est à cause de l'obscurcissement de Proguard - il a traité Parcelable. solution: Proguard provoquant une exception RuntimeException (code de type inconnu) dans la classe Parcelable
Il y a des règles pour écrire et lire les parcelles.
1- Faites attention à la disparité de type. Si vous écrivez int, n'essayez pas de lire longtemps, etc.
2- Faites attention à l'ordre des écritures et des lectures. Les objets doivent être dans le même ordre de tri lors de la lecture et de l'écriture.
Ces deux peuvent provoquer "Unmarshalling code de type inconnu".
Dans mon cas, il est corrigé après la mise à niveau de la bibliothèque de support vers 23.2.1.
Si un type de liste est ajouté, il devrait être:
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeList(this.mList);
et annulez-le en utilisant le type de classe comme ceci:
protected MyClass(Parcel in) {
super(in);
this.mList = new ArrayList<>();
in.readList(this.mList, MyRequiredClass.class.getClassLoader());
Ce n'est pas un problème lié à Proguard. Mais lorsque proguard et minify activent son occurrence de problème est toujours.
Le problème est dans la séquence d'écriture et de lecture d'objet ... la séquence doit être la même, c'est comme si vous lisiez un fichier.
Vous pouvez utiliser le plug-in de studio Android pour rendre la classe paramétrable https://plugins.jetbrains.com/plugin/7332?pr=
En utilisant Kotlin, l'objet 'Nota' a un objet personnalisé 'CentroCusto' qui ne contient que des propriétés primitives.
class Nota(var id: Int? = null, var centroCusto: ArrayList<CentroCusto>? = null) : Parcelable {
constructor(source: Parcel) : this(
source.readValue(Int::class.Java.classLoader) as Int?,
//Exception in below line -> Unmarshalling unknown type code
source.createTypedArrayList(CentroCusto.CREATOR)
)
override fun describeContents() = 0
override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
writeValue(id)
writeTypedList(centroCusto)
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator<Nota> = object : Parcelable.Creator<Nota> {
override fun createFromParcel(source: Parcel): Nota = Nota(source)
override fun newArray(size: Int): Array<Nota?> = arrayOfNulls(size)
}
}
La classe CentroCusto:
class CentroCusto(var id: Int? = null, var descricao: String? = null, var aprovacaoDiretoria: Int? = null, var permiteMarcar: Boolean? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readValue(Int::class.Java.classLoader) as? Int,
parcel.readString(),
parcel.readValue(Int::class.Java.classLoader) as? Int,
parcel.readValue(Boolean::class.Java.classLoader) as? Boolean) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeValue(id)
parcel.writeString(descricao)
parcel.writeValue(aprovacaoDiretoria)
parcel.writeValue(permiteMarcar)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<CentroCusto> {
override fun createFromParcel(parcel: Parcel): CentroCusto {
return CentroCusto(parcel)
}
override fun newArray(size: Int): Array<CentroCusto?> {
return arrayOfNulls(size)
}
}
}
Il suffit de supprimer toutes les méthodes pouvant être parcellisées et de les générer à nouveau avec une séquence valide.
Dans mon cas, ma classe n’a pas ajouté le fichier CREATOR lorsqu’il s’étend à partir d’un autre parent parcellaire.
public class Image implements Parcelable {
protected Image(Parcel in) {
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
@Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
@Override
public Image[] newArray(int size) {
return new Image[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
}
public class ImageChild extends Image {
protected ImageChild(Parcel in) {
super(in);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
}
Dans le champ CREATOR manquant dans ImageChild
Dans mon cas, cela est dû au fait que la taille des données dépassant la limite maximale pouvant être affectée à Parcel, qui est d'environ 1 Mo.
Solution: optimisez votre code parcellaire pour mettre le moins de données possible (par exemple, ne mettez pas d'objets Serializable dans Parcel)