Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing proguard with GSON and RoboGuice fails when using a EnumTypeAdapter
    primarykey
    data
    text
    <p>When trying to use a EnumTypeAdapter with Proguard, it results in a AssertionError in Gson.getAdapter(). This error seems to be due to type information being lost... below is all the relevant source code:</p> <p>The Exception:</p> <pre><code>03-18 13:27:12.905: ERROR/roboguice(12139): Throwable caught during background processing java.lang.AssertionError at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.&lt;init&gt;(Unknown Source) at com.google.gson.internal.bind.TypeAdapters$24.create(Unknown Source) at com.google.gson.Gson.getAdapter(Unknown Source) </code></pre> <p>The EnumTypeAdapter being used:</p> <pre><code>public class OperationResultSerializer implements JsonDeserializer&lt;OperationResult&gt;, JsonSerializer&lt;OperationResult&gt; { @Override public OperationResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { int value = json.getAsJsonPrimitive().getAsInt(); return OperationResult.values()[value]; } @Override public JsonElement serialize(OperationResult src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(src.ordinal()); } } </code></pre> <p>How I am constructing my GSON object: </p> <pre><code> gson = new GsonBuilder() .registerTypeAdapter(Calendar.class, new WcfCalendarSerializer()) .registerTypeAdapter(OperationResult.class, new OperationResultSerializer()) .registerTypeAdapter(FieldName.class, new FieldNameSerializer()) .registerTypeAdapter(MealType.class, new MealTypeSerializer()) .create(); </code></pre> <p>My ProGuard Config: </p> <pre><code>#-dontusemixedcaseclassnames: Necessary when building on windows where x.class and X.class is the same file -dontusemixedcaseclassnames -keepattributes *Annotation* -keepattributes Signature # Preserve the special static methods that are required in all enumeration classes. -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep public class * extends android.app.Application -keep public class * extends android.app.Activity -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep class * extends android.view.View { public &lt;init&gt;(android.content.Context); public &lt;init&gt;(android.content.Context, android.util.AttributeSet); public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int); public void set*(...); } -keep class com.google.inject.** { *; } -keep class javax.inject.** { *; } -keep class javax.annotation.** { *; } -keep class roboguice.** { *; } -keep class * extends android.preference.Preference { public &lt;init&gt;(android.content.Context); public &lt;init&gt;(android.content.Context, android.util.AttributeSet); public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int); public void set*(...); } # Gson specific classes -keep class sun.misc.Unsafe { *; } #-keep class com.google.gson.stream.** { *; } ###Action bar sherlock -keep class android.support.v4.app.** { *; } -keep interface android.support.v4.app.** { *; } -keep class com.actionbarsherlock.** { *; } -keep interface com.actionbarsherlock.** { *; } ###RoboGuice -keepclassmembers class * { @com.google.inject.Inject &lt;init&gt;(...); } -keepclassmembers class * { void *(**On*Event); } -keep public class roboguice.** -keep class com.google.inject.** -keep class com.google.gson.** {*;} #datacontract -keep public class com.ordering.datacontract.* -keepclassmembers class com.ordering.datacontract.* # LVL License binder class -keep class com.android.vending.licensing.ILicensingService -dontwarn -ignorewarnings </code></pre> <p>As stated earlier, I suspect something is failing due to type information being lost - after digging into the GSON source code, this is the code that is called to resolve the EnumTypeAdapter... clearly the getEnumConstants is returning a Name that does not exist as a field of the type classOfT. But I am unsure how that is possible. </p> <pre><code>private static final class EnumTypeAdapter&lt;T extends Enum&lt;T&gt;&gt; extends TypeAdapter&lt;T&gt; { private final Map&lt;String, T&gt; nameToConstant = new HashMap&lt;String, T&gt;(); private final Map&lt;T, String&gt; constantToName = new HashMap&lt;T, String&gt;(); public EnumTypeAdapter(Class&lt;T&gt; classOfT) { try { for (T constant : classOfT.getEnumConstants()) { String name = constant.name(); SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class); if (annotation != null) { name = annotation.value(); } nameToConstant.put(name, constant); constantToName.put(constant, name); } } catch (NoSuchFieldException e) { throw new AssertionError(); } } public T read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } return nameToConstant.get(in.nextString()); } public void write(JsonWriter out, T value) throws IOException { out.value(value == null ? null : constantToName.get(value)); } } </code></pre> <p>I have searched all over for possible solutions but have not found much help. Maybe someone has run into this before and can point me in the right direction? </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload