ProGuard et Gson sur Android (ClassCastException))
je passe un sacré moment avec Gson et ProGuard. J'ai un objet simple et quand je lis la méthode tojson, enregistrer sqllite et lire à partir de la base de données afin de charger le json retourné à mon objet, je reçois un java.lang.classcastexception. Si je n'utilise pas ProGuard, tout fonctionne très bien.
j'ai vérifié que la chaîne json envoyée et obtenu à partir de la base de données est la même. L'exception n'est levée lorsqu'il se convertit en json, mais plutôt quand j'essaie de accéder à l'objet.
Voici mon objet simple:
public class ScanLog extends ArrayList<SingleFrame>
{
private static final long serialVersionUID = 1L;
public ScanLog()
{
}
}
public final class SingleFrame
{
public int Position;
public int Time;
public Map<Integer,String> MainDataMap;
public Map<Integer,String> DataMap;
public SingleFrame(int position, int time,
Map<Integer,String> mainDataMap, Map<Integer,String> dataMap)
{
this.Position = position;
this.Time = time;
this.MainDataMap = mainDataMap;
this.DataMap = dataMap;
}
}
tous les autres aspects de mon application sont bons, mais quelque chose avec proguard est à l'origine de cela....J'ai essayé toutes sortes de commandes dans le proguard.cfg mais je ne suis pas sûr que ce que je fais soit juste.
EDIT - ADDING PROGUARD.CFG
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-dontshrink
-dontoptimize
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
#keep all classes that might be used in XML layouts
-keep public class * extends android.view.View
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.Fragment
#keep all classes
-keep public class *{
public protected *;
}
#keep all public and protected methods that could be used by java reflection
-keepclassmembernames class * {
public protected <methods>;
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keep public class org.scanner.scanlog.SingleFrame
-keepclassmembers class org.scanner.scanlog.ScanLog {
private <fields>;
public <fields>;
}
-keepclassmembers class org.scanner.scanlog.SingleFrame {
private <fields>;
public <fields>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-dontwarn **CompatHoneycomb
-dontwarn org.htmlcleaner.*
#-keep class android.support.v4.** { *; }
EDIT-OK J'ai obtenu ACRA mis en place avec succès dans mon application, fonctionnalité assez impressionnant! Ici, c'est le trace de la pile:
java.lang.ClassCastException: java.lang.Object
at org.scanner.activity.ReaderMainActivity.AdvanceScanLog(SourceFile:1499)
at org.scanner.activity.r.onProgressChanged(SourceFile:271)
at android.widget.SeekBar.onProgressRefresh(SeekBar.java:89)
at android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:507)
at android.widget.ProgressBar.refreshProgress(ProgressBar.java:516)
at android.widget.ProgressBar.setProgress(ProgressBar.java:565)
at android.widget.AbsSeekBar.trackTouchEvent(AbsSeekBar.java:337)
at android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:292)
at android.view.View.dispatchTouchEvent(View.java:3932)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1784)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1157)
at android.app.Activity.dispatchTouchEvent(Activity.java:2181)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1759)
at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2336)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1976)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
7 réponses
pour la dernière version du fichier de configuration proguard recommandé, veuillez consulter le logiciel android fourni par Gson à l'adresse suivante:: https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg
ces paramètres dans la configuration ont fonctionné pour moi dans une de mes applications:
# Add the gson class
-keep public class com.google.gson
# Add any classes the interact with gson
-keep class com.someapp.android.models.ChatModel { *; }
-keep class com.someapp.android.models.FeedModel { *; }
# Add the path to the jar
-libraryjars /Users/someuser/Documents/workspace/someapp/lib/gson-1.7.1.jar
J'espère que ça vous aidera.
appliquer les changements trouvés dans le exemple Android dans le projet Gson travaillé pour moi
les lignes nécessaires étaient:
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
# and keeping the classes that will be serialized/deserialized
je sais que la question originale a été résolue en adoptant une approche différente, mais j'avais un problème très similaire en utilisant flexjson et Proguard sur Android, et je l'ai résolu, au cas où quelqu'un tomberait dedans eux-mêmes.
lors de la conversion de retour de JSON à mon objet value qui incluait quelques ArrayLists, j'obtiendrais la même ClassCastException. Je l'ai fait fonctionner en ayant essentiellement obfuscation activé mais en éteignant toutes les parties de l'obfuscation (- garder tout, - keepclassmembers everything et-keepattributes everything) et ensuite travailler à l'envers en activant les choses un peu à la fois.
Le résultat; en gardant la totalité flexjson de la bibliothèque:
-keep class flexjson**
--keepclassmembers class flexjson** {
*;
}
et conserver la Signature et Annotation attribut:
-keepattributes Signature, *Annotation*
j'ai été en mesure d'utiliser la bibliothèque flexjson sans incident après cela dans une version proguarded, release de mon application.
j'ai eu des erreurs pour les classes modèles avec proguard si vous regardez
Gson Proguard vous trouverez une ligne
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
remplacer com.google.gson.examples.android.model.
par votre colis model
de même, dans mon cas, je l'ai remplacé par -keep class com.consumer.myProject.model.** { *; }
reste, j'ai copié en tant que tel
on dirait que vous gardez tout de votre classe (champs, méthodes et la classe elle-même). Mais pour être sûr que vous pouvez ajouter -printseeds outputfile.txt
au proguard.fichier cfg pour vérifier que proguard garde vraiment tout ce dont vous avez besoin une fois que la confusion est faite.
BTW, vous pourriez penser à ajouter quelque chose comme ACRA ou Android Remote stactrace qui vous permet d'inspecter stactraces sur une application construite.
donc, j'ai fini par abandonner la bibliothèque Gson et au lieu de convertir mon objet en json en utilisant gson, j'ai créé une classe personnalisée dans mon application pour sérialiser et désérialiser l'objet et stocker les données de cette façon.
je suis plus heureux, même si cela m'a coûté plus de 12 heures d'essayer de le comprendre. Apparemment, PROGUARD et gson ne doivent pas trop s'aimer?
en tant qu'avantage considérablement ajouté pour ne pas ayant à utiliser GSON, j'ai remarqué qu'en sortant la bibliothèque GSON, ma taille d'application est coupée en deux. Mon application était 577kb et est maintenant seulement 260kb après avoir enlevé la lib de gson.