78

私のプロジェクトは、オブジェクトのポリモーフィズム状態を保持するために、シリアライゼーション/デシリアライゼーション中にTypeAdapterin を実装しています。Gsonとにかく、プロジェクトは開発テスト中は問題なく動作しますが、プロガードの難読化でリリースしてテストすると、クラッシュするだけです。

03-21 10:06:53.632: E/AndroidRuntime(12441): FATAL EXCEPTION: main
03-21 10:06:53.632: E/AndroidRuntime(12441): java.lang.AssertionError
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(SourceFile:724)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.TypeAdapters$26.create(SourceFile:753)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson.getAdapter(SourceFile:353)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(SourceFile:82)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(SourceFile:81)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(SourceFile:118)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(SourceFile:72)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson.getAdapter(SourceFile:353)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson.toJson(SourceFile:578)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson.toJsonTree(SourceFile:479)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson.toJsonTree(SourceFile:458)
03-21 10:06:53.632: E/AndroidRuntime(12441):    at com.google.gson.Gson$3.serialize(SourceFile:137)

私のGson固有のproguard構成は次のとおりです。

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

#This is extra - added by me to exclude gson obfuscation
-keep class com.google.gson.** { *; }

##---------------End: proguard configuration for Gson  ----------

私が使用しているTypeAdapterは次のとおりです。

public final class GsonWorkshiftAdapter implements JsonSerializer<IWorkshift>, JsonDeserializer<IWorkshift> {
    private static final String CLASSNAME = "CLASSNAME";
    private static final String INSTANCE  = "INSTANCE";

    @Override
    public JsonElement serialize(IWorkshift src, Type typeOfSrc, JsonSerializationContext context) {
        String className = src.getClass().getCanonicalName();
        JsonElement elem = context.serialize(src);

        JsonObject retValue = new JsonObject();
        retValue.addProperty(CLASSNAME, className);
        retValue.add(INSTANCE, elem);

        return retValue;
    }

    @Override
    public IWorkshift deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject =  json.getAsJsonObject();
        JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
        String className = prim.getAsString();

        Class<?> klass = null;
        try { klass = Class.forName(className); }
        catch (ClassNotFoundException e) { throw new JsonParseException(e.getMessage()); }

        return context.deserialize(jsonObject.get(INSTANCE), klass);
    }
}

Gsonに固有のこのエラーについて多くの検索を行いましたが、役立つ答えが見つかりませんでした. ただし、同様の問題に関する別の質問が見つかりました。

開発者のコ​​ミュニティからの助けをいただければ幸いです。

4

7 に答える 7

198

列挙型のメンバーを保持するように要求する必要があるようです。これをproguard構成ファイルに追加すると、うまくいきました:

-keepclassmembers enum * { *; }

または、もっと具体的に言いたい場合は、

-keepclassmembers enum com.your.package.** { *; }
于 2015-05-11T11:55:42.433 に答える
14

シリアル化されたオブジェクトに関連するすべての列挙型をそのまま保持するように Proguard を構成する必要があることは既に示唆されています。すべての列挙型を明示的にリストする必要があるという事実はあまり好きではありません。このソリューションは維持するのが難しいです。私が思いついた少し良い解決策は次のとおりです。

空のインターフェイスを使用して、クラスまたは列挙型が Gson シリアル化に参加することを示します。

public interface GsonSerializable { }

public class MyClass implements GsonSerializable {

    public enum MyEnum implements GsonSerializable {
        enumvalue1, enumvalue2
    }

    public MyEnum mydata1;
}

インターフェイスとそれを実装するすべてのクラス/列挙型の両方を保持する Proguard 構成を使用します。

# keep GsonSerializable interface, it would be thrown away by proguard since it is empty
-keep class com.example.GsonSerializable

# member fields of serialized classes, including enums that implement this interface
-keepclassmembers class * implements com.example.GsonSerializable {
    <fields>;
}

# also keep names of these classes. not required, but just in case.
-keepnames class * implements com.example.GsonSerializable

それだけです。クラスと列挙型がインターフェイスを使用している限り、問題はありません。シリアライゼーション/デシリアライゼーション メソッドでこのインターフェイスの存在を強制することもできるので、後で新しいクラスを追加するときにそれを忘れることはありません。

public String serializeWithGson(GsonSerializable object) { ... }

また、構成では、「com.google.gson.examples.android.model.** { *;」の行があります。}' は Google 関連のサンプル コードを参照しているため、必要ないと思います。

于 2014-05-16T13:17:48.423 に答える
7

私の場合、proguard は Gson が触れる個々のクラスに構成されていましたが、これらの個々のクラスが存在するパッケージ-keepを保持するように proguard を構成すると、エラーはなくなりました。

-keep class com.company.library.model.** { *; }
于 2015-02-23T18:09:48.837 に答える
5

同じ問題に遭遇した後、結果の APK を逆コンパイルして調べました。この問題は、難読化中に一部の列挙型がメンバーを失うことに関連していると思います。

必ず列挙型を保持してください:

 -keepclassmembers enum * {
     public static **[] values();
     public static ** valueOf(java.lang.String);
 }

また、GSON で使用されているすべてのクラスが保持されていることを確認します。

 -keep public class com.company.ordering.datacontract.** {
     public protected *;
 }

 -keep public class com.company.ordering.service.request.** {
     public protected *;
 }
 -keep public class com.company.ordering.service.response.** {
     public protected *;
 }

@ pastebin.com/r5Jg3yY2 で完全な構成を参照してください。

于 2013-03-21T15:01:05.690 に答える
0

enum クラスにandroidx.annotation.Keepアノテーションを適用します。お気に入り:

@Keep
enum class PlayerType {
    PRO,
    INTERMEDIATE,
    BASIC
}
于 2022-01-05T11:56:31.477 に答える