web-dev-qa-db-fra.com

Comment réparer le code de type inconnu Unmarshalling XXX au décalage YYY sous Android?

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 Bundles et Serializables, 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?

23
4ntoine

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

10
4ntoine

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".

32
asozcan

Dans mon cas, il est corrigé après la mise à niveau de la bibliothèque de support vers 23.2.1.

4

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());
3
Subhas P

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=

2
Divy Sourabh

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

}
0
Ronaldo Albertini

Il suffit de supprimer toutes les méthodes pouvant être parcellisées et de les générer à nouveau avec une séquence valide.

0
Roshan

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

0
hovo888s

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)

0
Roman Minenok