如何在 Android Gradle 中从 ProGuard 排除一个库模块

8

我的Android应用程序的发布版本会崩溃,并显示以下异常:

java.lang.NoSuchMethodError: no static or non-static method "Lcom/mm/android/dhproxy/client/DHProxyClient;.InitWithName(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)I"

这个错误在调试版本中没有发现,所以我想是因为Proguard导致的。

上述提到的类位于其中一个模块中,该模块还使用JNI库。 我的app module文件的proguard-rules如下:

-keepattributes InnerClasses
-dontoptimize
-keep class com.mm.android.dhproxy.client.DHProxyClient
-keepclasseswithmembernames class * {
    native <methods>;
}
-keep class mypackage.MyCallbackClass {
    void myCallbackMethod(java.lang.String);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-printmapping build/outputs/mapping/release/mapping.txt

有关模块的build.gradle文件如下:

应用插件:'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    compileOptions.encoding = 'ISO-8859-1'

    defaultConfig {

        minSdkVersion 14
        targetSdkVersion 23
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile files('libs/IPlaySDK.jar')
    compile files('libs/ToUProxy.jar')
}

即使添加了以下代码,-keep class com.mm.android.dhproxy.client.DHProxyClient,我仍然可以看到usage.txt文件中包含以下条目。
com.mm.android.dhproxy.client.DHProxyClient:
    29:35:public boolean initWithName(java.lang.String,int,java.lang.String,java.lang.String)
    64:69:public int delPort(int)
    136:141:public int queryRate(int,com.mm.android.dhproxy.client.DHProxyRateParam)
    158:163:public int p2pSetOption(int,int)
    180:185:public int p2pGetOption(int)
    192:197:public int exit()
    private native int InitWithName(java.lang.String,int,java.lang.String,java.lang.String)
    private native int DelPort(int,int)
    private native int P2PSetOption(int,int,int)
    private native int P2PGetOption(int,int)
    private native int QueryRate(int,com.mm.android.dhproxy.client.DHProxyRateParam,int)
    private native int Exit(int)
com.mm.android.dhproxy.client.DHProxyRateParam

提前感谢您。

3个回答

11
解决方案是查找需要豁免的方法和类,并将它们添加到Proguard规则中,如下所示(此处我需要保留com.mm.**和com.company.**类中的文件,其中**充当通配符)。
-keep class com.mm.** {*;}
-keep class com.company.** {*;}
-keepclassmembers  class com.mm.** {*;}
-keepclassmembers  class com.company.** {*;}

1
谢谢您的回答。我没有加上两个星号和花括号中的子网掩码,它几乎做到了它需要做的事情。只是遗漏了构造函数。刚刚花了几天时间搜索崩溃的原因 :( - velis

5
如果您在主项目/应用程序中使用外部/独立源代码库,则不应在库模块上使用混淆。相反,您应该替换以下内容,
buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
    }
    debug {
        minifyEnabled false
    }
}

在库/库的build.gradle中添加以下内容:

buildTypes {
    release {
        consumerProguardFiles 'proguard-project.txt'
    }
}

其中 proguard-project.txt 是包含库项目的 ProGuard 规则的文件。在构建应用程序(无论是调试模式还是发布模式)时,编译器会处理所有规则(包括库和应用程序中的规则)。

来源:这个 stackoverflow 答案


0
你可以尝试将minifyEnabled设置为true,并使用以下命令生成发布版本构建。
如果你使用的是Mac,使用./gradlew assembleRelease;如果你使用的是Windows,则使用gradlew assembleRelease。
在运行命令后检查构建并查看是否有效。

我希望这个库在缩小处理过程中被豁免。 - dmSherazi
我认为如果你不将minifyenabled设置为true,你的proguard将被忽略。你是否使用我提到的命令生成了发布版本? - Avinash4551
发布 { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } - dmSherazi

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