使用 Gradle 和 ProGuard 构建的 Android:“输出 jar 必须在输入 jar 之后指定,否则将为空”

Posted

技术标签:

【中文标题】使用 Gradle 和 ProGuard 构建的 Android:“输出 jar 必须在输入 jar 之后指定,否则将为空”【英文标题】:Android Build with Gradle and ProGuard : "The output jar must be specified after an input jar, or it will be empty" 【发布时间】:2015-08-18 07:34:28 【问题描述】:

我正在使用 Gradle 创建具有不同风格的构建。直到现在它一直运行良好,直到我想启用Proguard。我为我的发布版本启用了minifyEnabled,现在我有一个异常说:

Caused by: org.gradle.internal.UncheckedException: java.io.IOException: The output jar [.../app/build/intermediates/multi-dex/dev/release/componentClasses.jar] must be specified after an input jar, or it will be empty.

有人知道是什么导致了这个异常吗?我基本上想在发布我的应用程序之前启用 ProGuard。下面是我的 Gradle 文件。

lintOptions 
    abortOnError false


dexOptions
    incremental true
    javaMaxHeapSize "4g"


defaultConfig 
        applicationId "..."
        minSdkVersion 14
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    

buildTypes 

    release 
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    

    debug 
        minifyEnabled false
        shrinkResources false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.debug
    

ProGuard 规则文件。

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/osayilgan/Development/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the javascript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview 
#   public *;
#

-keepnames public class * extends io.realm.RealmObject
-keep class io.realm.**  *; 
-dontwarn javax.**
-dontwarn io.realm.**

这是 proguard-android 文件。这是 Android SDK 中的默认设置。

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * 
    native <methods>;


# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View 
   void set*(***);
   *** get*();


# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity 
   public void *(android.view.View);


# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * 
    public static **[] values();
    public static ** valueOf(java.lang.String);


-keep class * implements android.os.Parcelable 
  public static final android.os.Parcelable$Creator *;


-keepclassmembers class **.R$* 
    public static <fields>;


# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

【问题讨论】:

你能提供你的proguard文件吗? @VicVu 我用 ProGuard 文件更新了我的问题。 【参考方案1】:

我花了很长时间才弄明白,但正如我所猜测的,这完全是关于 Proguard 的配置。

我开始挖掘控制台中的警告,并意识到 Proguard 找不到某些参考。所以将它们作为-dontwarn 添加到proguard 配置文件解决了这个问题。

就我而言,我不得不忽略下面的包;

-dontwarn java.lang.invoke**
-dontwarn org.apache.lang.**
-dontwarn org.apache.commons.**
-dontwarn com.nhaarman.**
-dontwarn se.emilsjolander.**

【讨论】:

嗨@osayilgan 我面临同样的问题。它对我不起作用,我把它放在我的 progurad 规则 pro 文件中。我应该把任何其他地方 @shivpaljodha 这些 proguard 规则只是一个示例。您需要找出哪些依赖项会给您带来麻烦。注意 LogCat 中的警告和错误,以便您弄清楚。

以上是关于使用 Gradle 和 ProGuard 构建的 Android:“输出 jar 必须在输入 jar 之后指定,否则将为空”的主要内容,如果未能解决你的问题,请参考以下文章

AndroidStudio 2.2 构建 gradle 错误(自定义 proguard 文件的路径)

构建android gradle项目时如何禁用proguard生成dump.txt

升级 gradle 后 Proguard 行为发生变化,从构建的 apk 中省略类

Gradle 在使用 Proguard 编译发布版本时无法找到一些引用和库类

定义了 Gradle 混乱 id 的 Proguard

Gradle:initwith 不适用于 minify 和 proGuard