android 库项目中的方法引用过多 - ClassNotFoundException

Posted

技术标签:

【中文标题】android 库项目中的方法引用过多 - ClassNotFoundException【英文标题】:Too many method references in android library project - ClassNotFoundException 【发布时间】:2015-11-07 08:15:45 【问题描述】:

我有一个库项目,我在使用 AAR 文件的主 android 项目中使用它。我现在得到了我所期望的著名的 65k 方法限制,但我有几个问题。

我在主项目的 libs 文件夹中添加了 AAR 文件,并在 build.gradle 中编译了相同的文件。

1) 我需要在库和主 android 项目中添加多 dex 支持吗?

2) 我需要在两个项目中添加 afterEvaluate 脚本吗?

最重要的是,如果我们让 multi-dex 工作,我们可能会在主 android 项目中遇到 Classnotfound 异常,如果我们尝试使用的任何类不在主 dex 列表中。

编辑:- 我正在尝试根据我的测试继续发布更新,以便任何有想法的人都可以帮助我们所有人。

项目中使用的依赖项:-

dependencies 
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile 'com.google.android.gms:play-services-gcm:7.8.0'
    compile 'com.google.android.gms:play-services-location:7.8.0'
    compile 'com.google.android.gms:play-services-ads:7.8.0'
    compile 'co.pointwise:pw-proto:0.0.5'
    compile 'com.amazonaws:aws-android-sdk-sns:2.2.1'
    compile 'com.amazonaws:aws-android-sdk-core:2.2.1'
    compile 'com.github.tony19:logback-android-core:1.1.1-4'
    compile 'com.github.tony19:logback-android-classic:1.1.1-4'
    compile 'org.slf4j:slf4j-api:1.7.6'
    compile 'com.android.support:multidex:1.0.0'
    compile(name: 'sdk-debug', ext: 'aar') // my library project

    // Crashlytics Kit
    compile('com.crashlytics.sdk.android:crashlytics:2.5.1@aar') 
        transitive = true
    

17-08-2015 - 根据文档,我修改了我的代码并使其现在可以工作,但我无法使用 proguard 生成签名的 apk。

Proguard 文件看起来像:-

-keep class ch.qos.**  *; 
-keep class org.slf4j.**  *; 
-keep class io.protostuff.**  *; 
-keep class com.google.common.**  *; 
-keep com.amazonaws.http.**  *; 
-keep com.amazonaws.internal.**  *; 
-keepattributes *Annotation*

-keep class * extends java.util.ListResourceBundle 
    protected Object[][] getContents();


# Keep SafeParcelable value, needed for reflection. This is required to support backwards
# compatibility of some classes.
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable 
    public static final *** NULL;


# Keep the names of classes/members we need for client functionality.
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * 
    @com.google.android.gms.common.annotation.KeepName *;


# Needed for Parcelable/SafeParcelable Creators to not get stripped
-keepnames class * implements android.os.Parcelable 
    public static final ** CREATOR;

错误:-

Warning: com.amazonaws.AmazonWebServiceClient: can't find referenced class org.apache.commons.logging.LogFactory
Warning: ch.qos.logback.core.net.SMTPAppenderBase: can't find referenced class javax.mail.internet.MimeMessage
Warning: com.google.common.base.Absent: can't find referenced class javax.annotation.Nullable
Warning: there were 1406 unresolved references to classes or interfaces.
         You may need to add missing library jars or update their versions.
         If your code works fine without the missing classes, you can suppress
         the warnings with '-dontwarn' options.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
Warning: there were 9 unresolved references to program class members.
         Your input classes appear to be inconsistent.
         You may need to recompile the code.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)
:app:proguardProdRelease FAILED

我之前也遇到过这个问题,在上一个项目中我无法解决它,但这次我需要解决它。

有什么想法吗?

【问题讨论】:

【参考方案1】:

首先,查看official documentation - 它详细解释了如何添加多 dex 支持。

答案:

我是否需要在库和主库中添加多 dex 支持 安卓项目?

仅在主 Android 项目中指定 'multiDexEnabled = true'(在 defaultConfig 下)。无需在库中声明。

我需要在两个项目中添加 afterEvaluate 脚本吗?

Android Gradle 插件 v0.14.0 增加了对 multi-dex 的支持,您不再需要添加您提到的代码。插件会自动创建主 dex 列表,并将所需信息传递给 dex 进程。

发布结果,如果您仍然有 ClassNotFoundException 错误,请告诉我们。

我在尝试构建版本时收到以下错误 带有 proguard 的变体: 警告:com.amazonaws.AmazonWebServiceClient: 找不到引用的类 org.apache.commons.logging.LogFactory

AWS 作者在他们的 github repo 中包含了 instructions 以了解如何设置 proguard 配置:

-keep class org.apache.commons.logging.**                *; 
-keep class com.amazonaws.services.sqs.QueueUrlHandler   *; 
-keep class com.amazonaws.javax.xml.transform.sax.*      public *; 
-keep class com.amazonaws.javax.xml.stream.**            *; 
-keep class com.amazonaws.services.**.model.*Exception*  *; 
-keep class com.amazonaws.internal.**                    *; 
-keep class org.codehaus.**                              *; 
-keep class org.joda.convert.*                           *; 
-keepattributes Signature,*Annotation*,EnclosingMethod
-keepnames class com.fasterxml.jackson.**  *; 
-keepnames class com.amazonaws.**  *; 

-dontwarn com.amazonaws.auth.policy.conditions.S3ConditionFactory
-dontwarn org.joda.time.**
-dontwarn com.fasterxml.jackson.databind.**
-dontwarn javax.xml.stream.events.**
-dontwarn org.codehaus.jackson.**
-dontwarn org.apache.commons.logging.impl.**
-dontwarn org.apache.http.conn.scheme.**
-dontwarn org.apache.http.annotation.**
-dontwarn org.ietf.jgss.**
-dontwarn org.w3c.dom.bootstrap.**

请注意,您的 proguard 配置缺少 org.apache.commons.logging.** 条目。

【讨论】:

是的,我关注了文档及其工作,但无法生成发布 apk。我已经更新了我的问题。 @Scorpion 你能用依赖列表更新你的问题吗?您使用的是哪个亚马逊库? @Scorpion 更新了答案,查看 AWS SDK proguard 说明。

以上是关于android 库项目中的方法引用过多 - ClassNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

Android开发笔记(一百七十九)避免方法数过多的问题

如何引用公共目录(不是库)中的外部 jar 文件来使用 ant 构建 android 项目?

android google play 库使用过多的 CPU 使用率

[Android] Android统计Apk , jar包方法数

多库项目中的 Android Studio proguard 处理

如何跨包引用Android“资产”?