在Android上使用Firebase需要哪些ProGuard配置?

54
当使用Firebase SDK开发Android应用时,我不断收到警告和错误信息,如以下内容(在Eclipse中):
Warning ... can't find referenced class ...
Warning: there were ... unresolved references to classes or interfaces ...
You may need to specify additional library jars (using '-libraryjars') ...

很遗憾,Firebase没有关于使用ProGuard的官方文档。

当使用ProGuard混淆时,我需要哪些指令才能成功编译带有Firebase的应用程序版本?


请参阅配置ProGuard - Kato
不幸的是,这并没有解决Coinverse应用程序的Firebase问题。您可以在此处查看完整代码(https://github.com/AdamSHurwitz/Coinverse)。 - AdamHurwitz
1
在使用实时数据库时,是否有类似于使用ProGuard配置的Firebase Firestore数据库的配置,如_配置Proguard_部分所述? - AdamHurwitz
12个回答

55
根据我的个人测试,结果表明对于使用ProGuard编译Firebase增强型Android应用程序,需要类似这样的内容。

无论如何,如果您在Firebase中使用自定义对象(即beans或POJO),则必须添加-keepnames class com.my.package.beans.** { *; }

Firebase SDK 1.0.18:
-keepnames class com.firebase.** { *; }
-keepnames class com.shaded.fasterxml.jackson.** { *; }
-keepnames class org.shaded.apache.** { *; }
-keepnames class javax.servlet.** { *; }
-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.commons.logging.impl.**

Firebase SDK 1.1.1:

-keep class com.firebase.** { *; }
-keep class org.shaded.apache.** { *; }
-keepnames class com.shaded.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.**
-dontwarn org.ietf.jgss.**

Firebase SDK 2.0.0:

-keep class com.firebase.** { *; }
-keep class org.apache.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.**
-dontwarn org.ietf.jgss.**

# Only necessary if you downloaded the SDK jar directly instead of from maven.
-keep class com.shaded.fasterxml.jackson.** { *; }

最后手段:

-keep class !com.my.package.** { *; }

注意:

任何官方指南都是受欢迎的。 -dontwarn 指令显然是危险的,代码可能会在我未测试的点上中断。此外,上述规则相当宽松,其他规则可能会更好地优化您的 APK。


2
我不得不添加-keepattributes Signature以使jackson正常工作。参考:https://dev59.com/N4fca4cB1Zd3GeqPmrpq - Riccardo Casatta
@RiccardoCasatta 你说得对,这是必需的。我只是忘了提到它,因为我已经有这个属性了。 - caw
1
在我们的 Slack 频道中:如果您正在使用 FirebaseUI,则需要添加以下行:-dontwarn com.firebase.ui.auth.** - Frank van Puffelen
1
你的 "如果在Firebase中使用自定义对象,例如bean或POJO" 保存了我的一天。因为没有这个规则,我的应用在生产环境中崩溃了。谢谢! - Billyjoker
我不知道BEAN/POJOS是什么意思,哈哈 后来在谷歌上查到,Beans/Pojos在Java中被称为模型类,用于封装数据。 我觉得这对像我一样的其他人可能会有所帮助:D - Nasib
显示剩余4条评论

17

我在 Firebase 文档中发现了这句话:

如果您在应用程序中使用 Firebase 实时数据库和 ProGuard,您需要考虑在混淆后如何序列化和反序列化模型对象。如果您使用 DataSnapshot.getValue(Class) 或 DatabaseReference.setValue(Object) 读写数据,您将需要向 proguard-rules.pro 文件添加规则:

# Add this global rule    
-keepattributes Signature

# This rule will properly ProGuard all the model classes in 
# the package com.yourcompany.models. Modify to fit the structure
# of your app.
-keepclassmembers class com.yourcompany.models.** {
*;
}

1
你能提供文档链接吗? - SalicBlu3
1
@SalicBlu3,这里是文档链接:https://firebase.google.com/docs/database/android/start#proguard。 - AdamHurwitz
不幸的是,这并没有解决Coinverse应用程序的Firebase问题。 - AdamHurwitz
@Keep注解也可以用于保留数据类。已测试并适用于Firebase:https://developer.android.com/guide/navigation/navigation-pass-data#use_keep_annotations - secretshardul

14

2021答案

在你的数据类之前使用@Keep注释,以便它们被Proguard保留。它是AndroidX的一部分,适用于JavaKotlin。可用于Firebase、Jetpack Navigator和Retrofit。

@Keep
data class Listing(
    val id: String = "",
    val name: String = ""
)

根据文档:

该注解用于标记某个元素,在代码构建时进行混淆(minified)时不应被移除。通常用在只通过反射访问的方法和类上,以避免编译器误认为代码未使用。


2
哇!你是一个救命恩人,提供了非常优雅的解决方案!谢谢你 :) - Rami Alloush
1
谷歌可以通过更新其文档来做得更好。 - secretshardul
1
你仍然需要添加-keep class com.google.firebase.** { *; },否则你的应用程序将无法在三星设备上运行,请参考:https://stackoverflow.com/a/59883426/2430555 - Pedro Paulo Amorim
已在三星设备上进行了测试,没有遇到任何问题。我们没有这个Proguard规则。 - secretshardul

9

虽然不是官方文档,但Firebase在其Github存储库中展示了一些基本的proguard规则。https://github.com/firebase/AndroidChat/blob/master/app/proguard-rules.pro

# Basic ProGuard rules for Firebase Android SDK 2.0.0+
-keep class com.firebase.** { *; }
-keep class org.apache.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.apache.**
-dontwarn org.w3c.dom.**

感谢提供这个源代码!与我的配置(请参见其他答案)的不同之处似乎在于,他们放弃了对org.joda.time.**org.shaded.apache.**org.ietf.jgss.**dontwarn规则,而是包含了一个org.apache.**的规则。 - caw
不用谢。我只是想加上它,因为它来自Firebase本身,而且与您个人的测试略有不同。 - user4989692

3

关于其它回答的跟进,使用Firebase 2.4.1时,我只需在我的混淆配置中包含以下内容(结果可能会有所不同):

-keep class com.firebase.** { *; }
-dontwarn com.fasterxml.**

3
配置Firebase 2.5.2似乎发生了改变。以下是我的有效配置:
-keep class com.firebase.** { *; }
-keep class org.apache.** { *; }
-keepnames class com.shaded.fasterxml.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.apache.**
-dontwarn org.w3c.dom.**

2

我使用的Firebase SDK 2.4.2工作集:

-keep class com.firebase.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.**
-dontwarn org.ietf.jgss.**
-dontwarn com.firebase.**
-dontnote com.firebase.client.core.GaePlatform

所以只有最后四个条目是新的,对吧?也许在这里加上一个“-dontwarn com.firebase.**”就足够了? - caw

1
我也曾经遇到过这个问题。感谢user4989692和Ugo指引我正确的方向。
以下是对我有用的方法:

build.gradle

    buildTypes {
    debug {
        minifyEnabled false
        shrinkResources false
        useProguard false
        debuggable true
        signingConfig signingConfigs.debug
    }
    release {
        minifyEnabled true
        shrinkResources true
        useProguard true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
}

proguard-rules.pro

-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.**
-dontwarn org.ietf.jgss.**
-dontwarn com.firebase.**
-dontnote com.firebase.client.core.GaePlatform

-keepattributes Signature
-keepattributes *Annotation*
-keepattributes InnerClasses,EnclosingMethod

-keep class com.YOUR-APP-DOMAIN.** { *; }

# Basic ProGuard rules for Firebase Android SDK 2.0.0+
-keep class com.firebase.** { *; }

-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }

18
您是希望禁用Proguard而不是仅仅保留com.YOUR-APP_DOMAIN吗?这似乎是不正确的。 - domenukk
1
根据 Firebase 的要求,您需要使用以下代码来保留与实时数据库一起使用的模型:-keepclassmembers class com.yourcompany.models.** { *; } - Tino

1
如果您正在使用Firebase实时数据库,则模型对象将在混淆后进行序列化和反序列化。
-keep class com.yourdevelopername.urappname.** { *; }

文档中的方法对你不起作用了吗,@Kaiffi? - AdamHurwitz
不幸的是,这并没有解决Coinverse应用程序的Firebase问题。您可以在此处查看完整代码(https://github.com/AdamSHurwitz/Coinverse)。 - AdamHurwitz

1
这就是为什么在使用清晰架构时很容易进行修复。看看这种情况,如果我的应用程序中有多个来自多个文件的 Firebase 请求,尝试保持单一类以使 Firebase 工作将会很混乱。因此,如果我们拥有模块化的代码,并将所有请求和数据模型存储在数据层中,那么只需保留使用 Firebase 的类而不是整个项目将更加容易。这样做也将有助于缩小 APK 大小。

enter image description here

-keep class com.mypackage.data.** {*;}

这就是我们所有人都在寻找的东西。 - Mostafa Onaizan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接