17

I try to compress an android app that consumes ical4j.jar.

When i build the apk with proguard using gradle proguardDebug i get

  • Warning: net.fortuna.ical4j.model.CalendarFactory: can't find referenced method 'void finalize()' in library class java.lang.Object
    • 6 additional similar warnings for finalize()
  • Warning: net.fortuna.ical4j.model.CalendarFactory: can't find referenced method 'java.lang.Object clone()' in library class java.lang.Object
    • 6 additional similar warnings for clone()

I already verified that android-7 supports finalize() and clone(): "...\Android...\sdk\platforms\android-7\android.jar" has methods finalize() and clone() in class java.lang.Object .

Do you have any idea how to fix this?

Note: this is not a duplicate of other 'proguard can't find referenced method' questions because in my specific case i think that the missing method should be there.

I am using

  • proguard-4.11 with
  • gradle-1.11
    • Groovy: 1.8.6
    • Ant: Apache Ant(TM) version 1.9.2 compiled on July 8 2013
    • Ivy: 2.2.0
    • JVM: 1.7.0_25 (Oracle Corporation 23.25-b01)
    • OS: Windows 7 6.1 amd64
  • ical4j.jar 1.0.5

this is proguard config proguard-rules.txt that probably need some fix:

#  proguard-rules.txt
## ical4j also contains groovy code which is not used in android 
-dontwarn groovy.**
-dontwarn org.codehaus.groovy.**
-dontwarn org.apache.commons.logging.**
-dontwarn sun.misc.Perf

-dontnote com.google.vending.**
-dontnote com.android.vending.licensing.**

This is my build.gradle

    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:0.9.+'
            classpath 'net.sf.proguard:proguard-gradle:4.11'
        }
    }

    allprojects {
        repositories {
            mavenCentral()
        }
    }

    apply plugin: 'android'

    configurations {
        compile.exclude group: 'commons-logging' // referenced in some portable lib. use androids internal instead
    }

    android {
        compileSdkVersion 19
        buildToolsVersion '19.0.3'

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

        defaultConfig {
            minSdkVersion 7
            targetSdkVersion 19
        }

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

            // used for testing. remove if it works as expected
            debug {
                runProguard true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
        }
    }

    dependencies {
        compile 'org.mnode.ical4j:ical4j:1.0.5'
        compile 'backport-util-concurrent:backport-util-concurrent:3.1'
        compile 'commons-codec:commons-codec:1.8'
        compile 'commons-lang:commons-lang:2.6'
    }

[Update 2014-12-20]

I have added my working configuration as answer below.

Note: with Current Android Studio 1.0 (android.buildToolsVersion >= '20') you must replace runProguard with minifyEnabled

Example

    android {
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
    }
k3b
  • 14,517
  • 7
  • 53
  • 85

3 Answers3

19

net.fortuna.ical4j.model.CalendarFactory extends groovy.util.AbstractFactory which extends java.lang.Object. However, the middle class is missing from your input (you're suppressing the corresponding warnings with -dontwarn). With part of the class hierarchy missing, ProGuard doesn't realize that CalendarFactory may access the protected methods clone and finalize, and it prints out these warnings.

Since your code probably doesn't use the class at all, you can suppress the warnings:

-dontwarn net.fortuna.ical4j.model.CalendarFactory

Or for covering all similar classes:

-dontwarn net.fortuna.ical4j.model.**

You shouldn't add any -keep options for this issue; the Android SDK already specifies the basic Android-related -keep options for you.

Eric Lafortune
  • 45,150
  • 8
  • 114
  • 106
  • i removed as proposed `-keep class net.fortuna.ical4j.model.** { *; }` that further reduced apk by extra 60 kb. furtunately my android app doesnt use any of the groovy-dependant classes. I updated my own answer with the final solution – k3b May 30 '14 at 10:49
2

This is my proguard config-file. Try copy-paste it

-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose    

# standard, except v4.app.Fragment, its required when app uses Fragments

-keep public class * extends android.app.Activity
-keep public class * extends android.support.v7.app.ActionBarActivity
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keepclasseswithmembers class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-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 * extends android.app.Activity { 
       public void *(android.view.View); 
}

Then add your code, as following: When using

-dontwarn groovy.**

also add

-keep class groovy.** { *; }

Do it for all external libraries.

Dawid C
  • 413
  • 3
  • 10
  • 1
    thanks for answer. i tried to add your config but the result was the same err. most android specific rules like `-keep public class * extends android.app.Activity` should come from `Android/.../tools/proguard/proguard-android(-optimize).txt` – k3b May 28 '14 at 09:28
  • did you tried to use -keep class ? I know that my file is using all of android specific rules. You may try turn of this system rules by removing ${sdk.dir}/tools/proguard/proguard-android.txt from project.properties file (that is when you use eclipse) – Dawid C May 28 '14 at 10:17
  • i did not use the keep for the groovy part because i donot want to keep the groovy part of the lib. However i am using the keep in my current workaround. I upvoted this answer from -1 to 0 because it helped me a lot although it was not the solution – k3b May 28 '14 at 11:03
-1

[update 2014-05-30 reformulated this text]

Thankyou to @EricLafortune answer that helped me to understand and solve the issue.

For others who want to compress android ical4j apps here is my working soluntion:

all classes with the in library class java.lang.Object - issue are from namespace

 net.fortuna.ical4j.model.**

so i added these lines to proguard-rules.txt

###################
# Get rid of #can't find referenced method in library class java.lang.Object# warnings for clone() and finalize()
# for details see http://stackoverflow.com/questions/23883028/how-to-fix-proguard-warning-cant-find-referenced-method-for-existing-methods
-dontwarn net.fortuna.ical4j.model.**

###############
# I use proguard only to remove unused stuff and to keep the app small.
# I donot want to obfuscate (rename packages, classes, methods, ...) since this is open source
-keepnames class ** { *; }
-keepnames interface ** { *; }
-keepnames enum ** { *; }

statistics:

  • without obfuscation: 932 classes; apk 911kb.
  • with obfuscation: 365 classes;apk 505kb
Ganapathy C
  • 5,989
  • 5
  • 42
  • 75
k3b
  • 14,517
  • 7
  • 53
  • 85