【问题标题】:Why am I getting a ClassNotFoundException from Play Services lib when using Proguard?为什么我在使用 Proguard 时会从 Play Services lib 获得 ClassNotFoundException?
【发布时间】:2017-01-09 18:42:29
【问题描述】:

我刚刚在我的构建中打开了 ProGuard,现在我得到了一个

java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.chimera.GmsModuleInitializer" on path: DexPathList[[zip file "/system/app/PlayGames.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]

文档说我需要将 Proguard 与 Play Services 一起使用的所有内容都应该包含在 Android Gradle 插件中:

注意:ProGuard 指令包含在 Play 服务客户端中 库以保留所需的类。 Android 插件 Gradle 自动在 AAR 中附加 ProGuard 配置文件 (Android ARchive) 打包并将该包附加到您的 ProGuard 配置。在项目创建过程中,Android Studio 会自动 创建 ProGuard 配置文件和 build.gradle 属性 供 ProGuard 使用。要将 ProGuard 与 Android Studio 一起使用,您必须启用 build.gradle buildTypes 中的 ProGuard 设置。更多 信息,请参阅 ProGuard 指南。

这是我的应用模块 build.gradle 文件的重要部分:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    defaultConfig {
        ...
    }
    ...
    buildTypes {
        ...{
            applicationIdSuffix ".debug"
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}


dependencies {
    ...

    //google play services
    compile 'com.google.android.gms:play-services-gcm:8.4.0'
    compile 'com.google.android.gms:play-services-analytics:8.4.0'
    compile 'com.google.android.gms:play-services-location:8.4.0'
}

这是我的顶级 build.gradle 文件:

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.2'
    }
}

allprojects {
    repositories {
        jcenter()
        mavenCentral()
    }
}

我错过了什么?

【问题讨论】:

    标签: google-play-services proguard


    【解决方案1】:

    ClassNotFoundException 通常发生在应用程序尝试通过其字符串名称加载类但找不到具有指定名称的类的定义时。

    从此forum,您可以通过添加com.google.android.gms.** { *; } 来修复它。

    只需添加到您的 proguard-project.txt:

    • 保留类 com.google.android.gms.** { *; }
    • 不要警告 com.google.android.gms.**

    您也可以查看SO question 中的建议评论。

    Google Play 服务 aars 包含带有必要条款的 proguard.txt。所以这个设置不应该真的是必要的。您可以调查 ProGuard 输出文件中的片段发生了什么。检查 app/build/output/mapping/{buildVariant}/usage.txt 和 mapping.txt。该片段应在其中之一中提及。

    希望这会有所帮助!

    【讨论】:

    • 谢谢。我添加了那些保持/不警告标志。很高兴知道他们“不应该”像我想的那样需要。我会调查输出映射。
    【解决方案2】:

    我知道这是一篇相当老的帖子,但我想强调以下内容,如果它对未来的人有所帮助。

    就像@abielita 提到的那样,ClassNotFoundException 是由未处理的反射情况引起的。

    当使用广泛的 -keep 选项(以 .** { *; } 结尾)时,您将指示 ProGuard 不要缩小、优化或混淆通配符之前提到的包名称的所有类和类成员。这最终会导致一个优化不佳的项目。因此,最好将此类-keep 选项缩小到仅针对缺失的类。在 OP 的示例中,为缺少的类添加 -keep 选项(如下所示)将解决此特定问题;

    -keep class com.google.android.gms.chimera.GmsModuleInitializer

    如果您将-addconfigurationdebugging 添加到配置文件中,ProGuard 可以帮助您设置缩小的-keep 选项,有关此功能的更多详细信息记录在ProGuard 手册here 中。

    最近发布了ProGuard Playground,您可以快速看到广泛的-keep 选项与缩小选项的效果。这里的一个很好的好处是您不需要不断(重新)构建项目。

    【讨论】:

      猜你喜欢
      • 2019-06-11
      • 2014-05-18
      • 2015-01-31
      • 1970-01-01
      • 2013-05-19
      • 2011-12-09
      • 2019-12-25
      • 2017-01-02
      • 2019-12-16
      相关资源
      最近更新 更多