I use Proguard to obfuscate my code, and make it smaller. I build using Eclipse, and have for some time. I've recently had a build that works great in the debug version, which I'm trying to release. I've been trying to get this done for most of the last day, and I keep getting the following error when I try to run my code using the released build (I can produce more if it helps).
02-25 16:39:58.844: E/AndroidRuntime(27593): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.kd7uiy.hamfinder.MainActivity" on path: DexPathList[[zip file "/data/app/com.kd7uiy.hamfinder-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.kd7uiy.hamfinder-2, /vendor/lib, /system/lib]]
The really strange thing is, I didn't change my proguard file, at least not the first time I did this. I've since been playing with it, to see if I can get anything to get it to work, but nothing seems to do the trick. Since this build, I have added a new library to my code base, the Google Maps utility library. My last build was only a few days ago.
Trying to troubleshoot this issue, I've found that there is an entire folder that doesn't appear on the path list. I see this folder in the compiled binary classes, but they don't survive the process. If I stop using Proguard, the release version works as intended.
My code relies on 6 packages that are in my /src
directory. I did not significantly alter this structure for this release, although I probably added a file or two to various folders, and might have moved a folder or two. The 6 packages are:
com.kd7uiy.hamfinder
com.kd7uiy.hamfinder.dialogs
com.kd7uiy.hamfinder.ObserverOutPairs
com.kd7uiy.hamfinder.Subjects
com.kd7uiy.library
com.robobunny
Of these, I can find no direct evidence of the following packages in my proguard mapping file, at least for this particular trial
com.kd7uiy.hamfinder
com.kd7uiy.hamfinder.ObserverOutPairs
com.kd7uiy.hamfinder.Subjects
Some have a few variable names referenced, but not evidence of the entire package being included. I've checked the .dex file, which does not contain the missing packages either. I should add, sometimes seemingly randomly some of the other packages will appear, but never the com.kd7uiy.hamfinder
, where my MainActivity resides. Sometimes none of them appear.
Here's my project.properties file:
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
android.library.reference.1=..\\..\\..\\Documents\\GitHub\\android-maps-utils\\library
android.library.reference.2=..\\..\\..\\..\\..\\Program Files (x86)\\Android\\android-sdk\\extras\\android\\support\\v7\\appcompat
android.library.reference.3=..\\..\\..\\..\\..\\Program Files (x86)\\Android\\android-sdk\\extras\\google\\google_play_services\\libproject\\google-play-services_lib
android.library.reference.4=..\\..\\..\\Documents\\GitHub\\android-styled-dialogs\\library\\src\\main
android.library.reference.5=..\\..\\..\\Documents\\GitHub\\drag-sort-listview\\library
And my original proguard-project.txt file, which has been shown not to work.
-keep class com.kd7uiy.hamfinder.MainSettingsActivity$GeneralPreferenceFragment
-keep class com.kd7uiy.hamfinder.MainSettingsActivity$LocationPreferenceFragment
-keep class com.android.vending.billing.**
-keep class jsqlite.** { *;}
-ignorewarnings
I did change it to add the appropriate Google Maps required changes for Proguard as well. Neither worked.
-keep class com.kd7uiy.hamfinder.MainSettingsActivity$GeneralPreferenceFragment
-keep class com.kd7uiy.hamfinder.MainSettingsActivity$LocationPreferenceFragment
-keep class com.android.vending.billing.**
-keep class jsqlite.** { *;}
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
@com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
#-keep class com.kd7uiy.hamfinder.AbstractReverseGeoCoder
-keep class com.kd7uiy.hamfinder.AbstractWebReverseGeoCoder
-dontwarn java.awt.**
-ignorewarnings
For reference here's my proguard-android.txt file, found in the correct location.
# 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.**
Here's a snapshot of my files
And here's my build path
Looking at some other files, I have seen evidence of the files in the /bin/proguard.txt
file, but they just seem to disappear after that. The compiled size isn't noticeably smaller either, but that could be because I have far more non-code stuff than code, it'd be hard to detect a difference of a few java files. Here's the entire /bin/proguard.txt file.
# view res/layout/activity_main.xml #generated:14
-keep class android.support.v4.view.ViewPager { <init>(...); }
# view large-land\res/layout-large-land/activity_main.xml #generated:2
# view large-port\res/layout-large-port/activity_main.xml #generated:2
# view res/layout/activity_main.xml #generated:1
# view xlarge-land\res/layout-xlarge-land/activity_main.xml #generated:2
# view xlarge-port\res/layout-xlarge-port/activity_main.xml #generated:2
-keep class android.support.v4.widget.DrawerLayout { <init>(...); }
# view res/layout/abc_action_menu_item_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ActionMenuItemView { <init>(...); }
# view res/layout/abc_action_menu_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ActionMenuView { <init>(...); }
# view res/layout/abc_expanded_menu_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ExpandedMenuView { <init>(...); }
# view res/layout/abc_list_menu_item_layout.xml #generated:17
# view res/layout/abc_popup_menu_item_layout.xml #generated:17
-keep class android.support.v7.internal.view.menu.ListMenuItemView { <init>(...); }
# view res/layout/abc_action_bar_decor_include.xml #generated:19
# view res/layout/abc_action_bar_decor_include.xml #generated:47
# view res/layout/abc_action_bar_decor_overlay.xml #generated:30
# view res/layout/abc_action_bar_decor_overlay.xml #generated:53
-keep class android.support.v7.internal.widget.ActionBarContainer { <init>(...); }
# view res/layout/abc_action_bar_decor_include.xml #generated:31
# view res/layout/abc_action_bar_decor_overlay.xml #generated:41
# view res/layout/abc_action_mode_bar.xml #generated:19
-keep class android.support.v7.internal.widget.ActionBarContextView { <init>(...); }
# view res/layout/abc_action_bar_decor_overlay.xml #generated:17
-keep class android.support.v7.internal.widget.ActionBarOverlayLayout { <init>(...); }
# view res/layout/abc_action_bar_decor_include.xml #generated:25
# view res/layout/abc_action_bar_decor_overlay.xml #generated:36
-keep class android.support.v7.internal.widget.ActionBarView { <init>(...); }
# view res/layout/abc_action_bar_home.xml #generated:17
-keep class android.support.v7.internal.widget.ActionBarView$HomeView { <init>(...); }
# view res/layout/abc_action_bar_tabbar.xml #generated:17
# view res/layout/abc_activity_chooser_view.xml #generated:19
-keep class android.support.v7.internal.widget.LinearLayoutICS { <init>(...); }
# view v11\res/layout-v11/abc_action_bar_decor.xml #generated:17
-keep class android.support.v7.internal.widget.NativeActionModeAwareLayout { <init>(...); }
# view res/layout/abc_action_bar_tab.xml #generated:17
-keep class android.support.v7.internal.widget.ScrollingTabContainerView$TabView { <init>(...); }
# view res/layout/abc_search_view.xml #generated:85
-keep class android.support.v7.widget.SearchView$SearchAutoComplete { <init>(...); }
# view AndroidManifest.xml #generated:72
-keep class com.google.analytics.tracking.android.CampaignTrackingReceiver { <init>(...); }
# view AndroidManifest.xml #generated:70
-keep class com.google.analytics.tracking.android.CampaignTrackingService { <init>(...); }
# view AndroidManifest.xml #generated:56
-keep class com.google.android.gms.ads.AdActivity { <init>(...); }
# view large-land\res/layout-large-land/activity_main.xml #generated:13
# view large-port\res/layout-large-port/activity_main.xml #generated:13
# view res/layout/activity_main.xml #generated:26
# view xlarge-land\res/layout-xlarge-land/activity_main.xml #generated:13
# view xlarge-port\res/layout-xlarge-port/activity_main.xml #generated:15
-keep class com.google.android.gms.ads.AdView { <init>(...); }
# view res/layout/google_map_dialog_preference.xml #generated:7
-keep class com.google.android.gms.maps.MapFragment { <init>(...); }
# view res/layout/google_map.xml #generated:2
# view res/layout/google_map_support_dialog_preference.xml #generated:7
-keep class com.google.android.gms.maps.SupportMapFragment { <init>(...); }
# view res/layout/text_bubble.xml #generated:8
-keep class com.google.maps.android.ui.RotationLayout { <init>(...); }
# view large-land\res/layout-large-land/activity_main.xml #generated:24
# view large-port\res/layout-large-port/activity_main.xml #generated:24
# view xlarge-land\res/layout-xlarge-land/activity_main.xml #generated:24
# view xlarge-port\res/layout-xlarge-port/activity_main.xml #generated:26
-keep class com.kd7uiy.hamfinder.LocationDisplayFragment { <init>(...); }
# view large-land\res/layout-large-land/activity_main.xml #generated:34
# view large-port\res/layout-large-port/activity_main.xml #generated:44
# view xlarge-land\res/layout-xlarge-land/activity_main.xml #generated:35
# view xlarge-port\res/layout-xlarge-port/activity_main.xml #generated:46
-keep class com.kd7uiy.hamfinder.LogBookFragment { <init>(...); }
# view AndroidManifest.xml #generated:40
-keep class com.kd7uiy.hamfinder.MainActivity { <init>(...); }
# view AndroidManifest.xml #generated:49
-keep class com.kd7uiy.hamfinder.MainSettingsActivity { <init>(...); }
# view res/xml/pref_location.xml #generated:43
-keep class com.kd7uiy.hamfinder.MapDialogPreference { <init>(...); }
# view large-land\res/layout-large-land/activity_main.xml #generated:45
# view large-port\res/layout-large-port/activity_main.xml #generated:33
# view xlarge-land\res/layout-xlarge-land/activity_main.xml #generated:47
# view xlarge-port\res/layout-xlarge-port/activity_main.xml #generated:35
-keep class com.kd7uiy.hamfinder.dialogs.SimpleLogFragment { <init>(...); }
# view res/layout/list_item_simple_checkable.xml #generated:3
# view v11\res/layout-v11/list_item_simple_checkable.xml #generated:3
-keep class com.kd7uiy.library.CheckableLinearLayout { <init>(...); }
# view AndroidManifest.xml #generated:59
-keep class com.kd7uiy.library.ManageAddOnPurchaseActivity { <init>(...); }
# view res/layout/mistake_form.xml #generated:14
-keep class com.kd7uiy.library.MapSpinner { <init>(...); }
# view res/layout/offline_map_dialog_preference.xml #generated:6
-keep class com.kd7uiy.library.SimpleMapView { <init>(...); }
# view res/xml/pref_general.xml #generated:19
# view res/xml/pref_general.xml #generated:26
# view res/xml/pref_location.xml #generated:4
-keep class com.kd7uiy.library.SortableListPreference { <init>(...); }
# view res/layout/wise_sayings_fragment.xml #generated:2
-keep class com.kd7uiy.library.WiseSayings { <init>(...); }
# view res/layout/sort_list_array_dialog_preference.xml #generated:2
-keep class com.mobeta.android.dslv.DragSortListView { <init>(...); }
# view res/xml/pref_location.xml #generated:12
# view res/xml/pref_location.xml #generated:20
# view res/xml/pref_location.xml #generated:28
-keep class com.robobunny.SeekBarPreference { <init>(...); }
I've also tried compiling with the ignorewarnings
flag disabled. The errors listed are huge, but here's a sampling of them, from the end:
[2014-02-26 10:03:37 - HamFinder] Proguard returned with error code 1. See console
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MainActivity: can't find superclass or interface com.kd7uiy.hamfinder.LogBookFragment$OnEditView
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MapQuestReverseCoder: can't find superclass or interface com.kd7uiy.hamfinder.AbstractWebReverseGeoCoder
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.OfflineLocator: can't find superclass or interface com.kd7uiy.hamfinder.AbstractReverseGeoCoder
[2014-02-26 10:03:37 - HamFinder] Warning: com.google.android.gms.auth.GoogleAuthUtil: can't find referenced class com.google.android.gms.R
...Continues like this. My searching shows mainly R files missing, although I did see this:
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MainActivity: can't find referenced class com.kd7uiy.hamfinder.MainActivity$2
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MainActivity: can't find referenced class com.kd7uiy.hamfinder.MainActivity$2
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MainActivity: can't find referenced class com.kd7uiy.hamfinder.MainActivity$3
[2014-02-26 10:03:37 - HamFinder] Warning: com.kd7uiy.hamfinder.MainActivity: can't find referenced class com.kd7uiy.hamfinder.MainActivity$3
...
[2014-02-26 10:03:37 - HamFinder] Warning: eu.inmite.android.lib.dialogs.SimpleTimePickerDialogFragment: can't find referenced class eu.inmite.android.lib.dialogs.R$layout
[2014-02-26 10:03:37 - HamFinder] Warning: eu.inmite.android.lib.dialogs.SimpleTimePickerDialogFragment: can't find referenced class eu.inmite.android.lib.dialogs.R$layout
[2014-02-26 10:03:37 - HamFinder] Warning: eu.inmite.android.lib.dialogs.SimpleTimePickerDialogFragment: can't find referenced class eu.inmite.android.lib.dialogs.R
[2014-02-26 10:03:37 - HamFinder] Warning: there were 678 unresolved references to classes or interfaces.
[2014-02-26 10:03:37 - HamFinder] You may need to add missing library jars or update their versions.
[2014-02-26 10:03:37 - HamFinder] If your code works fine without the missing classes, you can suppress
[2014-02-26 10:03:37 - HamFinder] the warnings with '-dontwarn' options.
[2014-02-26 10:03:37 - HamFinder] (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
[2014-02-26 10:03:37 - HamFinder] Warning: there were 11 unresolved references to program class members.
[2014-02-26 10:03:37 - HamFinder] Your input classes appear to be inconsistent.
[2014-02-26 10:03:37 - HamFinder] You may need to recompile the code.
[2014-02-26 10:03:37 - HamFinder] (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)
[2014-02-26 10:03:37 - HamFinder] java.io.IOException: Please correct the above warnings first.
[2014-02-26 10:03:37 - HamFinder] at proguard.Initializer.execute(Initializer.java:369)
[2014-02-26 10:03:37 - HamFinder] at proguard.ProGuard.initialize(ProGuard.java:211)
[2014-02-26 10:03:37 - HamFinder] at proguard.ProGuard.execute(ProGuard.java:86)
[2014-02-26 10:03:37 - HamFinder] at proguard.ProGuard.main(ProGuard.java:483)
I've tried quite a number of things to get this to work, including upgrading proguard, updating the SDK, updating the Eclipse tools, downloading a new version of Eclipse and starting from scratch, numerous changes to the proguard file, none of which seems to help in the slightest. Any other ideas?
EDIT- Here's a few things that I'm leaning towards, as a possibility.
- I've noticed that the warning list changes, even if I do nothing more than clean the project and re-build.
- The number of errors seems to grow with the number of times I've had eclipse opened and build the build.
- Eclipse seems to be crashing more frequently with heap errors.
Not sure if any of this helps, but I thought I'd toss it in there.
Right now you have
Your classes extend the support library v7 (judging from your project.properties) not the standard android.app.Activity, so you need something like:
or if you want to try to keep more (but bigger final apk):
or
and the same for
Fragment
s etcNote your log says Cannot find
LogBookFragment$OnEditView
which is an inner class View. Either list these one by one to save by proguard or move them out into their own class file.Summary: I'm pretty sure the key problem was the folder with the
/java
source folder instead of/src
. Make sure any dependent libraries have their source code in a/src
folder, if at all possible.As I hinted in my edit, I believe this is a memory problem. In fact, I was able to get the build built with a lot of trial and error, and a few adjustments made to my eclipse memory configuration. Specifically, I used the advice from this article, namely:
-Xmx256m
to-Xmx2048m
in the eclipse.ini file.-Xms256M -Xmx512M
to the JVM, found at Window-> Preferences -> Java -> Installed JREs -> clicking on JRE -> Edit-ignorewarnings
. That just masked the problem, I would have figured out what was going on a lot earlier if I hadn't done that.-dontwarn
for the known issues (A lib I use optionally usesjava.awt
, but not for the stuff I use...These steps helped, but in the end, I was able to fix it, although I did several things all at once, any of which could have fixed the problem. The things I did:
My project.properties looks like this now:
I occasionally receive reports about missing classes when building with ProGuard in Eclipse, in Windows. The cause is a mystery so far. ProGuard is run as a separate script/java process inside Eclipse. The problem happens spuriously. I am guessing the compiled class files aren't flushed to the file system in time for ProGuard to read them. You could try adding a pause or just list the files in the ProGuard script android-sdk/tools/proguard/bin/proguard.bat.
I have not received any similar reports about Ant or Gradle, so those may be practical alternatives.
(I am the developer of ProGuard)