【问题标题】:ProGuard for Android and GSON适用于 Android 和 GSON 的 ProGuard
【发布时间】:2014-07-12 15:11:20
【问题描述】:

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

我研究了与 GSON 和 Android 兼容的 ProGuard 配置,并遇到了 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 配置?

【问题讨论】:

    标签: java android configuration gson proguard


    【解决方案1】:

    我认为您的大部分设置已经默认包含在 Android SDK 中。

    因此您可以删除其中的大部分,只留下专门介绍 GSON 的部分。


    我正在使用 Android SDK Tools 22.6.3 和任何版本的 ProGuard 在 Eclipse 中进行开发。

    这是我用于 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.** { *; }
    

    它看起来和你的完全一样,除了我不需要关于注释的那一行。


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

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

    【讨论】:

    • 这是它的来源,顺便说一句:google-gson.googlecode.com/svn/trunk/examples/…
    • 在搜索了很多 QA 之后.. 我到达了这里。这让我开心。谢谢理查德。一张纸条,“mypersonalclass.data.model”,这对我来说不是必需的。检查一下。
    • @Noundla 更新了答案以解释 mypersonalclass.data.model 是占位符文本,应指向您自己的数据模型包。
    • 链接现在失效了
    • 非常感谢,有一个模型在不同的包中,需要添加该路径!
    【解决方案2】:

    上一个答案最近对我不起作用可能是由于 Android 的一些变化(现在使用 R8 而不是 Proguard)。我现在使用的配置如下(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 * implements 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>;
    }
    
    ##---------------End: proguard configuration for Gson  ----------
    

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 只需要一个*。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

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

        欲了解更多信息,请阅读本文

        PS - 这就是我为 Gson 所做的

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

        【讨论】:

        • “使用 -keep 是一种不好的做法,你永远不应该这样做”背后的原因是什么?顺便说一句,keepclassmembernames 在我们的设置中不起作用,所有字段都被删除。只有keepkeepclassmembers 真正保留它们。
        猜你喜欢
        • 2011-09-25
        • 2016-12-02
        • 2015-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-18
        • 2016-02-11
        相关资源
        最近更新 更多