4

I use MultiDex and ProGuard in my Android app. When I run my app it turns out that proguard runs twice. Here are the tasks after which proguard runs:

:app:transformClassesAndResourcesWithProguardForRelease
ProGuard, version 5.2.1
...
Initializing...
Shrinking...
Obfuscating...
Writing output...

and later:

:app:transformClassesWithMultidexlistForRelease
ProGuard, version 5.2.1

Here is my app's build.gradle file:

buildscript {
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }

    dependencies {
        classpath 'io.fabric.tools:gradle:1.20.1'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'com.google.gms.google-services'


android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "de.majestella"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 3
        versionName "1.0.1"

        // Enabling multidex support.
        multiDexEnabled true
    }

    dexOptions {
        incremental true
        javaMaxHeapSize "2g"
    }


    buildTypes {
        debug {
            debuggable true

            // ProGuard
            minifyEnabled false
        }
        release {
                signingConfig signingConfigs.release

                debuggable false

                // ProGuard
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'),
                        'proguard-rules.pro', 'proguard-guava.pro', 'proguard-square-picasso.pro',
                        'proguard-crashlytics.pro', 'proguard-google-analytics.pro'

       }

    }

}

repositories {
    mavenCentral()
    maven {
        name = "sonatype"
        url = "https://oss.sonatype.org/content/repositories/snapshots/"
    }
    maven {
        name = "sonatypeGoogle"
        url = "https://oss.sonatype.org/content/repositories/google-snapshots/"
    }
    flatDir {
        dirs 'libs'
    }
    maven { url 'https://maven.fabric.io/public' }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'


    compile('com.crashlytics.sdk.android:crashlytics:2.5.2@aar') {
        transitive = true;
    }

    compile 'com.android.support:multidex:1.0.1'

    compile 'com.google.android.gms:play-services-analytics:8.1.0'
    compile "com.google.android.gms:play-services:8.1.0"

}

After the first proguard run (i.e., after :app:transformClassesAndResourcesWithProguardForRelease) I get the following warnings after writing output, so proguard itself works fine here with my rules:

Warning: can't write resource [fabric/com.crashlytics.sdk.android.answers.properties] (Duplicate zip entry [fabric/com.crashlytics.sdk.android.answers.properties])
Warning: can't write resource [fabric/com.crashlytics.sdk.android.beta.properties] (Duplicate zip entry [fabric/com.crashlytics.sdk.android.beta.properties])
Warning: can't write resource [fabric/com.crashlytics.sdk.android.crashlytics-core.properties] (Duplicate zip entry [fabric/com.crashlytics.sdk.android.crashlytics-core.properties])
Warning: can't write resource [fabric/com.crashlytics.sdk.android.crashlytics.properties] (Duplicate zip entry [fabric/com.crashlytics.sdk.android.crashlytics.properties])
Warning: can't write resource [fabric/io.fabric.sdk.android.fabric.properties] (Duplicate zip entry [fabric/io.fabric.sdk.android.fabric.properties])

When the second proguard run takes place after :app:transformClassesWithMultidexlistForRelease I get the following:

Note: android.support.design.widget.CoordinatorLayout calls 'Class.getAnnotation'
Note: com.google.ads.mediation.MediationServerParameters calls 'Field.getAnnotation'
Note: com.google.common.eventbus.AnnotatedSubscriberFinder calls 'Method.getAnnotation'
Note: com.google.common.reflect.Invokable$MethodInvokable calls 'Method.getParameterAnnotations'
Note: d.a.a.a.c calls 'Class.getAnnotation'
Note: d.a.a.a.i calls 'Class.getAnnotation'
Note: android.support.v4.app.ak calls 'Field.getType'
Note: com.google.android.gms.internal.zzsf calls 'Field.getType'
...

This is strange because in the first proguard run I get no warnings/notes like this because of my rules.

Here are my ProGuard rules:

-keep class com.google.common.io.Resources {
    public static <methods>;
}
-keep class com.google.common.collect.Lists {
    public static ** reverse(**);
}
-keep class com.google.common.base.Charsets {
    public static <fields>;
}
-keep class com.google.common.collect.MapMakerInternalMap$ReferenceEntry
-keep class com.google.common.cache.LocalCache$ReferenceEntry

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-keepattributes SourceFile,LineNumberTable,*Annotation*
-keep class com.crashlytics.android.**



-dontwarn com.squareup.okhttp.**

-dontnote org.apache.http.conn.**
-dontnote org.apache.http.params.**
-dontnote android.net.http.**

-dontnote **ILicensingService
-dontnote com.android.vending.billing.IInAppBillingService


-dontwarn com.google.auto.factory.**

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod


-dontnote android.support.**
-dontnote com.google.common.util.concurrent.**
-dontnote com.squareup.okhttp.**

-keep class org.jsoup.** { *; }
-keeppackagenames org.jsoup.nodes
-keep class com.google.common.cache.Striped64 { *; }
-keep class com.google.common.** { *; }
-keep class com.daimajia.slider.** { *; }


-dontnote org.jsoup.**
-dontnote com.google.common.**
-keep class com.squareup.picasso.** { *; }
-keep class com.google.android.gms.** { *; }
-keep class com.google.ads.** { *; }
-keep class com.lorentzos.** { *; }
-keep public class com.google.android.gms.* { public *; }
-dontwarn com.google.android.gms.**

-dontnote com.google.android.gms.maps.internal.CreatorImpl

-keep class com.mikepenz.iconics.** { *; }

It seems to me like the second ProGuard run does not use my proguard rules.

Edit: Here is the result of gradlew -q tasks --all: https://gist.github.com/confile/2a15d80980214656f4f1

Why does the second Proguard run raises errors and how can I resolve them?

Michael
  • 32,527
  • 49
  • 210
  • 370
  • I don't see any errors from ProGuard in your question, only "notes". – m0skit0 Oct 19 '15 at 16:29
  • Try running `gradlew -q tasks --all` to figure out where it comes from. It will list all tasks with their dependencies. (It can be useful to write the output to a file, for easy searching.) – kevinpelgrims Oct 22 '15 at 12:38
  • @kevinpelgrims What should I search for? – Michael Oct 22 '15 at 16:04
  • You should be able to find where it runs the ProGuard task. If it is in two completely different places, you might be able to figure out how to disable one of them. – kevinpelgrims Oct 23 '15 at 06:35
  • @kevinpelgrims I did not change any of the default Android build process. Does it belongs to multi dex? – Michael Oct 23 '15 at 13:59
  • @kevinpelgrims Here is the result https://gist.github.com/confile/2a15d80980214656f4f1 it seems like there is only one proguard task but it is called twice. – Michael Oct 23 '15 at 14:02