适用于 Android 和 GSON 的 ProGuard

发布于 2025-01-12 14:04:55 字数 3806 浏览 0 评论 0原文

我正在为我的 Android 项目设置 ProGuard。我的项目也使用GSON。

我研究了 ProGuard 配置与 GSON 和 Android 的兼容性,并发现了 google-gson https://code.google.com/p/google-gson/source/browse/trunk/examples/android-proguard-example/proguard.cfg

ProGuard 配置复制如下:

##---------------Begin: proguard configuration common for all Android apps ----------
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-allowaccessmodification
-keepattributes *Annotation*
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
-repackageclasses ''

-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
-dontnote com.android.vending.licensing.ILicensingService

# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# Preserve static fields of inner classes of R classes that might be accessed
# through introspection.
-keepclassmembers class **.R$* {
  public static <fields>;
}

# 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 * {
    public protected *;
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
##---------------End: proguard configuration common for all Android apps ----------

##---------------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.** { *; }

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

问题:

  1. 我看到该文件自 2011 年以来就没有更新过,是否仍建议使用?我问这个问题是因为 Android/GSON 从那时起已经发生了很大的变化,所以我不知道上面的内容有多少是不必要的或不正确的。

  2. 如果不推荐,Android 中的 GSON 是否有新的推荐 ProGuard 配置?

I'm setting up ProGuard for my Android project. My project also uses GSON.

I've researched ProGuard configurations for compatibility with GSON and Android and came across this example offered by google-gson https://code.google.com/p/google-gson/source/browse/trunk/examples/android-proguard-example/proguard.cfg.

ProGuard config copied below:

##---------------Begin: proguard configuration common for all Android apps ----------
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-dump class_files.txt
-printseeds seeds.txt
-printusage unused.txt
-printmapping mapping.txt
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-allowaccessmodification
-keepattributes *Annotation*
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
-repackageclasses ''

-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
-dontnote com.android.vending.licensing.ILicensingService

# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# Preserve all native method names and the names of their classes.
-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# Preserve static fields of inner classes of R classes that might be accessed
# through introspection.
-keepclassmembers class **.R$* {
  public static <fields>;
}

# 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 * {
    public protected *;
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
##---------------End: proguard configuration common for all Android apps ----------

##---------------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.** { *; }

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

Questions:

  1. I see that this file has not been updated since 2011, is it still recommended for use? I ask because Android/GSON has changed quite a bit since then so I don't know how much of the above in unnecessary or incorrect.

  2. If this is not recommended, is there a new recommended ProGuard configuration for GSON in Android?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

離人涙 2025-01-19 14:04:55

我认为默认情况下,您拥有的大部分设置已经包含在 Android SDK 中。

因此,您可以删除其中的大部分内容,只保留专门用于 GSON 的部分。


我正在 Eclipse 中使用 Android SDK Tools 22.6.3 & 进行开发无论 ProGuard 附带什么版本。

这是我用于 GSON 2.2.4 的内容(按照他们的示例):

##---------------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

# 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 mypersonalclass.data.model.** { *; }

它看起来与您所拥有的完全相同,只是我不需要有关注释的行。


你可以看到我注释掉了一些我自己添加的类。如果您序列化/反序列化自己的类,则需要在此处声明它们以代替对 mypersonalclass.data.model 的引用。这非常重要,因为您不希望 ProGuard 混淆 GSON 用于序列化的字段或类名称。

我总是在那里留下这些类型的注释,所以我知道如何配置下一个库或应用程序。

I think most of those settings you have there are already included in the Android SDK by default.

So you can remove most of them, just leaving in the section devoted to GSON.


I am developing in Eclipse using Android SDK Tools 22.6.3 & whatever version of ProGuard ships with that.

Here's what I'm using for GSON 2.2.4 (as per their example):

##---------------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

# 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 mypersonalclass.data.model.** { *; }

It looks exactly the same as what you have, except I don't need the line about the annotations.


You can see I've commented out some classes that I added myself. If you serialize/deserialize your own classes, you need to declare them here in place of the reference to mypersonalclass.data.model. This is really important, as you don't want ProGuard to obfuscate the field or class names that GSON uses for serialization.

I always leave those types of comments in there, so I know how to configure the next library or app.

冷血 2025-01-19 14:04:55

之前的答案最近对我不起作用,可能是由于 Android 的一些变化(现在使用 R8 而不是 Proguard)。我现在使用的配置如下(源 - GSON 示例):

##---------------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
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

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

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

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

我发现字段由 @SerializedName 注解的类不必显式列出,除非它们是内部类。

The previous answer stopped working for me recently probably due to some changes in Android (R8 is used now instead of Proguard). The configuration I use now is as follows (source - GSON examples):

##---------------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
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

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

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

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

I found out that classes whose fields are annotated by @SerializedName do not have to be explicitly listed unless they are inner classes.

装迷糊 2025-01-19 14:04:55

就我而言,我只是使用 GSON 将 JSON 反序列化为对象。因此,将以下行添加到 proguard 文件就足够了。

-keep class your.data.object.modals.package.** { <fields>; }

In my case, I just used GSON for deserializing JSON to an Object. So it was enough to add the following line to proguard file.

-keep class your.data.object.modals.package.** { <fields>; }
我爱人 2025-01-19 14:04:55

就我而言,我添加了上述内容,但仍然出现错误,直到在我的应用程序级别 gradle 中,我将 compile 'org.immutables:gson:2.4.6' 更改为 provided 'org.immutables:gson :2.4.6'。也许更开明的人可以解释原因,但这解决了我的问题。

In my case I added the above but still got an error until in my app level gradle I changed compile 'org.immutables:gson:2.4.6' to provided 'org.immutables:gson:2.4.6'. Maybe someone more enlightened can explain why but this solved my problem.

南风几经秋 2025-01-19 14:04:55

使用 -keep 是一种不好的做法,你永远不应该这样做。你几乎不想使用 -keep;如果您确实需要 ProGuard 规则,您通常需要更具体的变体之一

-keepclassmembers - 这仅保护类的成员免遭收缩和混淆。

-keepnames - 这允许缩小类和成员,但不允许混淆。也就是说,任何未使用的代码都将被删除。但保留的代码将保留其原始名称。

-keepclassmembernames - 未使用的类被删除,其余的类被重命名,这些类的未使用的成员被删除,但其余的成员保留其原始名称。

欲了解更多信息,请阅读此

PS - 这是我为 Gson 所做的

-keepclassmembernames class rscom.pojo.** { <fields>; }

Using -keep is a bad practice and you should never do it .You almost never want to use -keep; if you do need a ProGuard rule, you usually want one of the more specific variants

-keepclassmembers - This protects only the members of the class from shrinking and obfuscation.

-keepnames - This allows shrinking for classes and members, but not obfuscation. That is, any unused code is going to get removed. But the code that is kept will keep its original names.

-keepclassmembernames - Unused classes are removed, the remaining classes are renamed, unused members of those classes are removed, but then the remaining members keep their original names.

For more information please read this

PS - this is what I did for Gson

-keepclassmembernames class rscom.pojo.** { <fields>; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文