My app works perfectly on both emulated and real 1.6 devices. However The Sony Xperia X10 series (running 1.6) is crashing with a java.lang.VerifyError. This thread leads me to believe ProGuard optimization could be the culprit, but if that were the case wouldn't the problem exist on every device running 1.6, instead of just the X10?
Here is the stack trace:
java.lang.VerifyError: com.twocell.walkabout.Animator
at com.twocell.walkabout.Main.void onCreate(android.os.Bundle)(SourceFile:197)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2443)
at android.app.ActivityThread.access$2100(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1815)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Here is the code that triggers the error (in a class called 'Animator'):
static void setLayoutAnimation_textFadeIn(ViewGroup vg, Context context)
{
Animation text_fadeIn = AnimationUtils.loadAnimation(context, R.anim.text_fade_in);
LayoutAnimationController controller = new LayoutAnimationController(text_fadeIn, 0.25f);
vg.setLayoutAnimation(controller);
}
which is called from:
LinearLayout HeaderBar_Text = (LinearLayout) findViewById(R.id.HeaderBar_Text);
Animator.setLayoutAnimation_textFadeIn(HeaderBar_Text, this); // this is line 197
and here is text_fade_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1000"
/>
</set>
I don't have access to an X10 so I'm relying on stack traces delivered via ACRA.
EDIT (new info):
Ok, I was able to find an old emulator image of the X10 running 1.6 and re-create the problem. Turns out, it /is/ only crashing on the release (ProGuard) version. Turn off ProGuard and it works perfectly. Why on earth this only affects the X10 and not every single 1.6 device is the question. Here is some new info I've gathered since I have the emulator...
On some of my Activities I'm using overridePendingTransition
to change to a fading effect, however this is not supported on 1.6, so I'm using a helper class called VersionHelper:
class VersionHelper
{
static void overrideTransition(Context context)
{
((Activity)context).overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out);
}
}
and it's called from Animator:
static void overrideTransition(Context context)
{
if (Build.VERSION.SDK_INT > 4)
{
VersionHelper.overrideTransition(context);
}
}
This allows 1.6 devices to run the rest of the code without crashing from the unsupported method (Thanks to Mark Murphy for this technique).
Now, the stack trace with extra log data:
07-19 23:42:29.150: ERROR/dalvikvm(705): Could not find method android.app.Activity.overridePendingTransition, referenced from method com.twocell.walkabout.Animator.overrideTransition
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: unable to resolve virtual method 14: Landroid/app/Activity;.overridePendingTransition (II)V
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: rejecting opcode 0x6e at 0x0012
07-19 23:42:29.150: WARN/dalvikvm(705): VFY: rejected Lcom/twocell/walkabout/Animator;.overrideTransition (Landroid/content/Context;)V
07-19 23:42:29.150: WARN/dalvikvm(705): Verifier rejected class Lcom/twocell/walkabout/Animator;
07-19 23:42:29.160: DEBUG/AndroidRuntime(705): Shutting down VM
07-19 23:42:29.160: WARN/dalvikvm(705): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): Uncaught handler: thread main exiting due to uncaught exception
07-19 23:42:29.160: ERROR/AndroidRuntime(705): java.lang.VerifyError: com.twocell.walkabout.Animator
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.twocell.walkabout.Main.onCreate(SourceFile:199)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.access$2100(ActivityThread.java:116)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.os.Handler.dispatchMessage(Handler.java:99)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.os.Looper.loop(Looper.java:123)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at android.app.ActivityThread.main(ActivityThread.java:4203)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at java.lang.reflect.Method.invokeNative(Native Method)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at java.lang.reflect.Method.invoke(Method.java:521)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
07-19 23:42:29.160: ERROR/AndroidRuntime(705): at dalvik.system.NativeStart.main(Native Method)
So there it is - when I use ProGuard, and only on the X10, it's still seeing overridePendingTransition
and crashing. (I confirmed that the X10 /is/ reporting "4" as its API version.)
Finally, my proguard.cfg:
-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
-keep class com.android.vending.billing.**
-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 *;
}
#ACRA specifics
# we need line numbers in our stack traces otherwise they are pretty useless
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
# ACRA needs "annotations" so add this...
-keepattributes *Annotation*
# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
*;
}
# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
*;
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public void addCustomData(java.lang.String,java.lang.String);
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable);
}
-keep class org.acra.ReportField {*;}
Any thoughts?
Edit 2
Using -dontoptimize
in ProGuard lets the app run on the X10. I'm sneaking up on a solution.