Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't build APK with Android Studio when using ProGuard minification

I have a problem generating the APKs of my applications.

If i debug/run the app, it works normally. But when I try to generate the corresponding APK, Android Studio gives me a lot of warnings and one error:

Note: there were 159 duplicate class definitions.
  (http://proguard.sourceforge.net/manual/troubleshooting.html#duplicateclass)
Warning:com.thoughtworks.xstream.converters.reflection.CGLIBEnhancedConverter$ReverseEngineeredCallbackFilter: can't find superclass or interface net.sf.cglib.proxy.CallbackFilter
Warning:org.apache.harmony.awt.datatransfer.DataProxy: can't find superclass or interface java.awt.datatransfer.Transferable
Warning:org.apache.harmony.awt.datatransfer.NativeClipboard: can't find superclass or interface java.awt.datatransfer.Clipboard
Warning:library class android.content.res.XmlResourceParser extends or implements program class org.xmlpull.v1.XmlPullParser
Warning:library class org.apache.http.auth.AuthenticationException extends or implements program class org.apache.http.ProtocolException
[...]
Warning:library class org.apache.http.impl.conn.LoggingSessionOutputBuffer extends or implements program class org.apache.http.io.SessionOutputBuffer
Warning:com.itextpdf.testutils.ITextTest: can't find referenced class javax.management.OperationsException
Warning:com.itextpdf.text.pdf.BarcodeCodabar: can't find referenced class java.awt.Color
[...]
Warning:com.itextpdf.text.pdf.security.MakeXmlSignature: can't find referenced class javax.xml.crypto.dsig.spec.C14NMethodParameterSpec
[...]
Warning:com.sun.mail.handlers.image_gif: can't find referenced class java.awt.datatransfer.DataFlavor
[...]
Warning:com.sun.mail.imap.protocol.IMAPSaslAuthenticator: can't find referenced class javax.security.sasl.Sasl
[...]
Warning:com.thoughtworks.xstream.converters.extended.ColorConverter: can't find referenced class java.awt.Color
[...]
Warning:org.apache.harmony.awt.ContextStorage: can't find referenced class java.awt.Toolkit
[...]
Warning:org.spongycastle.jce.provider.X509LDAPCertStoreSpi: can't find referenced class javax.naming.directory.InitialDirContext
[...]
Warning:library class android.content.Intent depends on program class org.xmlpull.v1.XmlPullParser
[...]
Warning:library class org.apache.http.client.HttpClient depends on program class org.apache.http.HttpResponse
[...]
Warning:library class org.xmlpull.v1.XmlPullParserFactory depends on program class org.xmlpull.v1.XmlPullParser
Warning:there were 1077 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 141 instances of library classes depending on program classes.
         You must avoid such dependencies, since the program classes will
         be processed, while the library classes will remain unchanged.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#dependency)
Warning:there were 5 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)
:vet:proguardInternalRelease FAILED
Error:Execution failed for task ':PROJECTNAME:proguardInternalRelease'.
> java.io.IOException: Please correct the above warnings first.
Information:BUILD FAILED
Information:Total time: 13.878 secs
Information:1 error
Information:679 warnings
Information:See complete output in console

The project is formed by a library project, imported as external project like this in settings.gradle:

include ':library'
project(':library').projectDir = new File(settingsDir, '../Library/library')

with all the dependencies.

The build.gradle of the library is

apply plugin: 'com.android.library'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 21
        multiDexEnabled true
    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }

}

dependencies {
    compile 'com.google.android.gms:play-services:+'
    compile 'com.android.support:support-v13:21.0.+'
    compile 'com.android.support:multidex:1.0.0'
    compile('ch.acra:acra:4.5.0') {
        exclude group: 'org.json'
    }
    compile 'org.apache.httpcomponents:httpcore:4.3'
    compile('org.apache.httpcomponents:httpmime:4.3.1') {
        exclude group: 'org.apache.httpcomponents', module: 'httpcore'
        exclude group: 'org.apache.httpcomponents', module: 'httpclient'
    }
    compile('javax.mail:mail:1.4.7') {
        exclude module: 'activation'
    }
    compile 'com.madgag.spongycastle:pkix:1.50.0.0'
    compile 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
    compile ('com.itextpdf.tool:xmlworker:5.5.1'){
        exclude module: 'itextpdf'
    }
    compile('com.thoughtworks.xstream:xstream:1.4.4') {
        exclude group: 'xmlpull', module: 'xmlpull'
    }
    compile 'com.google.zxing:core:3.0.1'
    compile files('libs/activation.jar')
    compile files('libs/additionnal.jar')
    compile files('libs/miniTemplator.jar')
    compile files('libs/itextg-5.5.1.jar')
}

and the project build.gradle is

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "my.package.name"
        minSdkVersion 15
        targetSdkVersion 21
        multiDexEnabled true
    }

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

    productFlavors {
        def BOOLEAN = "boolean"
        def TRUE = "true"
        def FALSE = "false"
        def A_FIELD= "A_FIELD"

        internal {
            buildConfigField BOOLEAN, A_FIELD, FALSE
        }

        official {
            buildConfigField BOOLEAN, A_FIELD, TRUE
        }
    }


    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
}

dependencies {
    compile project(':library')
}

afterEvaluate {
    tasks.matching {
        it.name.startsWith('dex')
    }.each { dx ->
        if (dx.additionalParameters == null) {
            dx.additionalParameters = []
        }
        dx.additionalParameters += '--multi-dex'
    }
}

How do I fix it so the APK can be compiled?

EDIT: After added a lot of -dontwarn options to my proguard-rules.pro, I got the error anyway, and I can't resolve these warnings (Here there are some hints, but not for these warnings...):

Warning:com.itextpdf.text.pdf.security.PdfPKCS7: can't find referenced method 'ASN1Integer(int)' in program class org.spongycastle.asn1.ASN1Integer
Warning:com.sun.activation.viewers.ImageViewer: can't find referenced method 'java.awt.Component add(java.awt.Component)' in program class com.sun.activation.viewers.ImageViewer
Warning:com.sun.activation.viewers.ImageViewer: can't find referenced method 'java.awt.Toolkit getToolkit()' in program class com.sun.activation.viewers.ImageViewer
Warning:com.sun.activation.viewers.ImageViewer: can't find referenced method 'void invalidate()' in program class com.sun.activation.viewers.ImageViewer
Warning:com.sun.activation.viewers.ImageViewer: can't find referenced method 'void validate()' in program class com.sun.activation.viewers.ImageViewer
Warning:com.sun.activation.viewers.ImageViewer: can't find referenced method 'void doLayout()' in program class com.sun.activation.viewers.ImageViewer
Warning:com.sun.activation.viewers.ImageViewerCanvas: can't find referenced method 'void invalidate()' in program class com.sun.activation.viewers.ImageViewerCanvas
Warning:com.sun.activation.viewers.ImageViewerCanvas: can't find referenced method 'void repaint()' in program class com.sun.activation.viewers.ImageViewerCanvas
Warning:com.sun.activation.viewers.TextEditor: can't find referenced method 'void setLayout(java.awt.LayoutManager)' in program class com.sun.activation.viewers.TextEditor
Warning:com.sun.activation.viewers.TextEditor: can't find referenced method 'void invalidate()' in program class com.sun.activation.viewers.TextEditor
Warning:com.sun.activation.viewers.TextViewer: can't find referenced method 'void setLayout(java.awt.LayoutManager)' in program class com.sun.activation.viewers.TextViewer
Warning:com.sun.activation.viewers.TextViewer: can't find referenced method 'java.awt.Component add(java.awt.Component)' in program class com.sun.activation.viewers.TextViewer
Warning:com.sun.activation.viewers.TextViewer: can't find referenced method 'void invalidate()' in program class com.sun.activation.viewers.TextViewer
Warning:javax.activation.ActivationDataFlavor: can't find referenced method 'boolean isMimeTypeEqual(java.awt.datatransfer.DataFlavor)' in program class javax.activation.ActivationDataFlavor
Warning:there were 14 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)
:vet:proguardInternalRelease FAILED
Error:Execution failed for task ':vet:proguardInternalRelease'.
> java.io.IOException: Please correct the above warnings first.
like image 949
Garro88 Avatar asked Dec 29 '14 11:12

Garro88


People also ask

How do I enable R8 on my Android?

Enabling R8 in your project To enable R8, open build. gradle module app file and add this piece of code inside the buildTypes . The code inside the release{} block means that this will be applied to the release build version of your application. If you launch the app in the emulator, this code is not executed.

What is the difference between ProGuard and R8?

R8 is having a faster processing time than Proguard which reduces build time. R8 gives better output results than Proguard. R8 reduces the app size by 10 % whereas Proguard reduces app size by 8.5 %. The android app having a Gradle plugin above 3.4.


1 Answers

These are obnoxious to cleanup. The better libraries are now including their settings in the library package, but older (or lazier) ones still aren't. Here is the process I follow:

While developing:

  • Whenever a new library is included, make sure to check its documentation for their suggested ProGuard settings. (If you are diligent with this it saves a lot of confusion and digging later.)
  • If the library author offers an AAR package (for example adding '@aar' to the end of the gradle dependency line to get the full AAR instead of the simpler JAR) they might have even included the necessary ProGuard exceptions in there for you that will automatically get picked up. (But in my experience, most authors still aren't taking this extra step yet.)
  • Whenever a new namespace/class is added in custom code that needs dynamic introspection, for example when using dependency injection containers or JSON parsers, make sure ProGuard is set to pick them up based on their package name, or add them yourself one class at a time.

After building and getting errors:

  • Start with all the lines that start with the prefix error: then warning: (the note: lines won't stop a build).
  • Check the namespace each line mentions. Find the associated library (for example com.newrelic.SomeClass is probably for the New Relic library). If you can't find it, try a Google search to see if the namespace can help you track down the github README or something else that might identify which library that namespace includes. Or, check the Android Studio > Project > Packages > Libraries list (takes awhile to display the first time) and track down the namespace there. Hopefully the source code will be available and include the library details in the file header comments.
  • Lookup the documentation for that library. Hopefully it mentions the necessary ProGuard changes.
  • Rebuild.

All the changes the library docs said are in, but still getting warnings:

  • Start adding -dontwarn lines. For example: -dontwarn com.newrelic.** (Don't forget the double asterisk so it ignores the whole tree under that namespace; otherwise a single asterisk will only ignore the direct children of the namespace.)
  • If you start using blind dontwarn statements, you must test your compiled app (APK)! Because it is now highly probably that it will crash on you, even though the debug (non-ProGuard) version has been running fine. Make sure to test all the libraries you used, check logcat messages, and make sure you exercise all the code paths/classes that you are blindly skipping with dontwarn!

Screw it, my boss said I have to release this thing already:

  • Disable ProGuard :-(

Either use the project properties dialog in Android Studio, or edit your module build.gradle file and change the android { buildTypes { release { minifyEnabled true } } } and set it to false.

You won't get ProGuard optimizations, the APK will be much larger, and code won't be obfuscated. But if your boss just needs it out now and you don't have time to debug, it won't be the end of the world to disable it.

Though you really should be using ProGuard. Perhaps it's time to talk to the boss about giving the developers more time to do the boring technical things we need to.

like image 164
Jon Adams Avatar answered Oct 26 '22 05:10

Jon Adams