Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42642

Exclude Java SE library from Android proguard

In Android, I have proguard with the following settings.

-dontpreverify

# Hold onto the mapping.text file, it can be used to unobfuscate stack traces in the developer console using the retrace tool
-printmapping mapping.txt

# Keep line numbers so they appear in the stack trace of the develeper console
-keepattributes SourceFile,LineNumberTable 

# The -optimizations option disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle.
-optimizations !code/simplification/arithmetic 

# Activities, services and broadcast receivers are specified in the manifest file so they won't be automatically included
-keep public class * extends android.app.Activity
-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 

# Custom view components might be accessed from your layout files
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

# event handlers can be specified in the layout files e.g. android:onClick="nextButton_onClick", I borrowed this method name notation from .NET
-keepclassmembers class * extends android.app.Activity {
    public void *_*(android.view.View);
}

# Parcelable implementations are accessed by introspection
-keepclassmembers class * implements android.os.Parcelable {
    static android.os.Parcelable$Creator CREATOR;
}

# You might want to keep your annotations
-keepattributes *Annotation*

# I use Google Guava in my app
# see http://code.google.com/p/guava-libraries/wiki/UsingProGuardWithGuava
-libraryjars libs/google/jsr305-1.3.9.jar;libs/pinyin4j/pinyin4j-2.5.0.jar
-dontwarn sun.misc.Unsafe

-keepclasseswithmembers class com.google.common.base.internal.Finalizer{
    <methods>;
}

Some of my library, are directly imported from Java SE (Contains JApplet for example)

How I can exclude them from proguard? Note, I have pinyin4j-2.5.0.jar library in -libraryjars. I thought that's the way to tell proguard, "Hey, this is a library. Don't do anything on it, OK?" But, seems like proguard still trying to process pinyin4j-2.5.0.jar

I'm getting the following errors.

Note: there were 125 duplicate class definitions.
Warning: demo.Pinyin4jAppletDemo: can't find superclass or interface javax.swing.JApplet
Warning: demo.Pinyin4jAppletDemo$1: can't find superclass or interface java.awt.event.WindowAdapter
Warning: demo.Pinyin4jAppletDemo$2: can't find superclass or interface java.awt.event.ActionListener
Warning: demo.Pinyin4jAppletDemo$3: can't find superclass or interface java.awt.event.ActionListener
Warning: org.jasypt.encryption.pbe.PBEBigDecimalCleanablePasswordEncryptor: can't find superclass or interface org.jasypt.encryption.pbe.PBEBigDecimalEncryptor
Warning: org.jasypt.encryption.pbe.PBEBigIntegerCleanablePasswordEncryptor: can't find superclass or interface org.jasypt.encryption.pbe.PBEBigIntegerEncryptor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyDescriptor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyDescriptor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyEditor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyEditor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyEditor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyEditorManager
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyDescriptor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.IntrospectionException
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyEditor
Warning: au.com.bytecode.opencsv.bean.CsvToBean: can't find referenced class java.beans.PropertyDescriptor
...
...
Warning: org.jasypt.normalization.Normalizer: can't find referenced class com.ibm.icu.text.Normalizer$Mode
      You should check if you need to specify additional program jars.
Warning: there were 333 unresolved references to classes or interfaces.
         You may need to specify additional library jars (using '-libraryjars').
Warning: there were 6 unresolved references to program class members.
         Your input classes appear to be inconsistent.
         You may need to recompile them and try again.
         Alternatively, you may have to specify the option 
         '-dontskipnonpubliclibraryclassmembers'.
Error: Please correct the above warnings first.

Some of you may comment that for library jars which contain Java SE only methods (like Applet, Swing, ...) cannot be used in Android. Nope. In fact, they run perfectly fine, as long as you consume their non-Java SE-only methods.

The full error log can be downloaded from here : https://www.dropbox.com/s/dns62f7gp6unusg/error-log.txt

Upvotes: 0

Views: 3744

Answers (3)

AlexWien
AlexWien

Reputation: 28727

Example to keep java runtime (rt.jar)

<libraryjar file="${java.home}/lib/rt.jar" />

It seems that your line

-libraryjars libs/google/jsr305-1.3.9.jar;libs/pinyin4j/pinyin4j-2.5.0.jar

is not complete. Update But since the needed classes do not exist on android, you have to ignore these warnings. But do not generally ignore obfuscation warnings, we had a serious bug (using an obfuscation.map in file), because we ignored all warnings.

Upvotes: 1

Eric Lafortune
Eric Lafortune

Reputation: 45648

If you are sure that these Java SE classes are not used, you can indeed ignore the warnings (as you have found in your own answer). An easier way to specify this:

-dontwarn java.beans.**
-dontwarn java.awt.**
-dontwarn javax.swing.**

See ProGuard manual > Troubleshooting > Warning: can't find referenced class

Similar questions with always the same answer:

Upvotes: 6

Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42642

I merely avoid the error by

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-dontwarn javax.swing.**
-dontwarn java.awt.**
-dontwarn org.jasypt.encryption.pbe.**
-dontwarn java.beans.**
-dontwarn org.joda.time.**
-dontwarn com.google.android.gms.**
-dontwarn org.w3c.dom.bootstrap.**
-dontwarn com.ibm.icu.text.**
-dontwarn demo.**

Here's the complete proguard configuration

-optimizationpasses 1
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#-dontobfuscate

-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-dontwarn javax.swing.**
-dontwarn java.awt.**
-dontwarn org.jasypt.encryption.pbe.**
-dontwarn java.beans.**
-dontwarn org.joda.time.**
-dontwarn com.google.android.gms.**
-dontwarn org.w3c.dom.bootstrap.**
-dontwarn com.ibm.icu.text.**
-dontwarn demo.**

# Hold onto the mapping.text file, it can be used to unobfuscate stack traces in the developer console using the retrace tool
-printmapping mapping.txt

# Keep line numbers so they appear in the stack trace of the develeper console 
-keepattributes *Annotation*,SourceFile,LineNumberTable

-keep public class * extends android.app.Activity
-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
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }

# https://sourceforge.net/p/proguard/discussion/182456/thread/e4d73acf
-keep class org.codehaus.** { *; }

-assumenosideeffects class android.util.Log {
  public static int d(...);
  public static int i(...);
  public static int e(...);
  public static int v(...);  
}

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

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

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

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
}

# I use Google Guava in my app
# see http://code.google.com/p/guava-libraries/wiki/UsingProGuardWithGuava
-libraryjars libs/google/jsr305-1.3.9.jar

-keepclasseswithmembers class com.google.common.base.internal.Finalizer{
    <methods>;
}

It doesn't work completely out of box yet as I still experience crash in "after proguard generated" APK.

Is pretty hard for me to find out why it crashes, as the code is obfuscate.

If I specific dontobfuscate, I will get another set of problem during generation. A message "Conversion to Dalvik format failed with error 1" pop up without additional information. But, that's another set of different problem.

Upvotes: 0

Related Questions