2

My application will debug and run perfectly fine on my target device (HTC Desire HD) when the application is installed via USB from Eclipse.

However, when I export to .APK and then install this .APK on my Desire HD (having first manually uninstalled the previous installation of my application), it crashes.

Having inspected the error in Logcat I can see that a custom extended View of mine, that is referenced using its fully-qualified name in a layout XML file, apparently cannot be found and leads to a .classNotFoundException.

The two lines of interest from the Logcat error trace are:

04-09 21:29:01.101: E/AndroidRuntime(2157): Caused by: android.view.InflateException: Binary XML file line #12: Error inflating class com.trevp.myAppName.DashboardLayout

And further below:

04-09 21:29:01.101: E/AndroidRuntime(2157): Caused by: java.lang.ClassNotFoundException: com.trevp.myAppName.DashboardLayout in loader dalvik.system.PathClassLoader[/data/app/com.trevp.myAppName-1.apk

This crash does not occur when the application is installed from Eclipse, only when installed from an exported .APK.

In case this could be a Proguard issue, here is my Proguard configuration file. I haven't really touched it from default, as I'm new to using Proguard. My Proguard version is 4.7.

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

-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

-keepclasseswithmembernames class * {
    native <methods>;
}

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

-keepclasseswithmembernames 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 *;
}

The XML file that is being inflated. (Merge tags are used because the elements within are added as children to the parent FrameLayout.)

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView   
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="top|left"
    android:scaleType="centerCrop"
    android:id="@+id/dashLayoutImage"
    android:src="@drawable/background2" android:drawingCacheQuality="high"/>

    <com.trevp.myAppName.DashboardLayout
    android:clipChildren="false"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/dashLayout"
    android:layout_gravity="top|left" />

    <include
    android:layout_gravity="top|left"
    layout="@layout/status_bar"
    android:id="@+id/statusBar" />

    <TextView
    android:layout_gravity="bottom|left"
    android:id="@+id/pollRate"
     android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    </TextView>

</merge>

Thanks in advance for any tips on this. Please shout if there are any other extracts or configuration information required.

Trevor
  • 10,903
  • 5
  • 61
  • 84
  • please share the xml file that is causing the inflation. – Anurag Ramdasan Apr 09 '12 at 20:44
  • @Anurag Ramdasan - Good point, thank you. I've added the XML layout now. – Trevor Apr 09 '12 at 20:47
  • Have you tried accessing the `DashboardLayout` object in the activity? Try doing that to see if it is proguard the one that is removing the class. Actually, you can also open the DEXed jar to see if the class is there. If it's not, then it most likely is proguard. – dmon Apr 10 '12 at 00:28
  • @dmon - Many thanks, I'll give that a go. I've just come to realise that, considering Proguard is enabled and is obfuscating my class names as it should be (which I've confirmed by checking that a mapping.txt was generated during the release build I last attempted), surely there's something wrong in the fact that an XML layout is being inflated and is referencing my `View` class by its original name! Presumably, Proguard needs to be configured so that obfuscated layout class names are somehow substituted into XML resources prior to them being compressed. I'll investigate this now. – Trevor Apr 10 '12 at 07:43
  • Ah yes, you might want to turn off obfuscation too (`-dontobfuscate`) – dmon Apr 10 '12 at 13:59
  • @dmon thanks for your suggestion. I have just tried `-dontobfuscate` and oddly the export process fails with `Conversion to Dalvik format failed with error 1`, which is an error I had previously eliminated by updating my Proguard version. Prior to doing that, I also tried `-keep public class com.trevp.myAppName.DashboardLayout`, and all output files (i.e. Proguard report .txt files and the actual .APK) remained exactly the same, i.e. originally reported crash problem persists. – Trevor Apr 10 '12 at 15:50

3 Answers3

3

This problem has been now fixed by using a completely standard and default proguard.cfg file taken from a freshly created test project.

The configuration file I was previously using, as quoted in my original question, was one that I had to add to the project manually a short time back because it was missing. I am not sure where the file came from now -- I had most probably Googled and found a sample default file and just used it.

Here is the one that Eclipse put into the new project for me, and that enabled a working .APK.

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


-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

-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 *;
}

I can see that the differences are in the -keepclass* type instructions.

I will now make more of an effort to actually understand how to configure Proguard!

For the sake of interest, looking at the following lines:

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

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

These look like they're there to preserve View constructors (or, preserve the classes that contain them) that would only be called when the class is referenced from XML.

Trevor
  • 10,903
  • 5
  • 61
  • 84
0

not setting your attachToRoot to true while inflating the view with merge could be a reason for InflateException.

Anurag Ramdasan
  • 4,189
  • 4
  • 31
  • 53
0

Or you can just replace the one in the project by the default one or the optimized one in ${sdk.dir}/tools/proguard/proguard-android.txt

Driss Bounouar
  • 3,182
  • 2
  • 32
  • 49