I created an app for the software conference I organize, Code on the Beach, with Xamarin Android that was originally targeting v19 for 4.4 KitKat. It worked well. I upgraded Xamarin to use the latest version to get v21 Lollipop support, and added the Toolbar to get the material design style action bar, which required me to implement ActionBarActivity which implements the support FragmentActivity, and trying to use the regular FragmentManager no longer worked. Okay, so I converted it all to use SupportFragmentManager and make sure all my Fragments were of the v4 support variety, despite that I only want to target 4.0+.
Now, I get a Java NullPointerException in the call to base.OnSaveInstanceState(outState)
whenever I rotate the screen, even if my OnSaveInstanceState method is trivial and just calls the base class:
Attempt to read from field 'android.os.Handler android.support.v4.app.FragmentActivity.mHandler' on a null object reference
Here's my practically-empty OnSaveInstanceState method, to show I'm not doing anything funky:
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
}
Here's what the application output log shows:
[MonoDroid] UNHANDLED EXCEPTION:
[MonoDroid] Java.Lang.NullPointerException: Exception of type 'Java.Lang.NullPointerException' was thrown.
[MonoDroid] at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x00068>
[MonoDroid] at Android.Runtime.JNIEnv.CallNonvirtualVoidMethod (intptr,intptr,intptr,Android.Runtime.JValue[]) [0x00084] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:896
[MonoDroid] at Android.App.Activity.OnSaveInstanceState (Android.OS.Bundle) [0x00070] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-21/src/generated/Android.App.Activity.cs:3890
[MonoDroid] at CodeOnTheBeach.MobileApp.Android.BaseActivity.OnSaveInstanceState (Android.OS.Bundle) [0x00001] in c:\Users\Paul\Documents\Xamarin\CodeOnTheBeach.MobileApp\CodeOnTheBeach.MobileApp.Android\Activities\BaseActivity.cs:241
[MonoDroid] at Android.App.Activity.n_OnSaveInstanceState_Landroid_os_Bundle_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.21-series/49a04b96/source/monodroid/src/Mono.Android/platforms/android-21/src/generated/Android.App.Activity.cs:3875
[MonoDroid] at (wrapper dynamic-method) object.bab595ee-4bb8-44e2-9d58-a36175f89b29 (intptr,intptr,intptr) <IL 0x00017, 0x00043>
[MonoDroid] --- End of managed exception stack trace ---
[MonoDroid] java.lang.NullPointerException: Attempt to read from field 'android.os.Handler android.support.v4.app.FragmentActivity.mHandler' on a null object reference
[MonoDroid] at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1464)
[MonoDroid] at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1672)
[MonoDroid] at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:524)
[MonoDroid] at codeonthebeach.mobileapp.android.BaseActivity.n_onSaveInstanceState(Native Method)
[MonoDroid] at codeonthebeach.mobileapp.android.BaseActivity.onSaveInstanceState(BaseActivity.java:100)
[MonoDroid] at android.app.Activity.performSaveInstanceState(Activity.java:1297)
[MonoDroid] at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1272)
[MonoDroid] at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:3923)
[MonoDroid] at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3886)
[MonoDroid] at android.app.ActivityThread.access$900(ActivityThread.java:144)
[MonoDroid] at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
[MonoDroid] at android.os.Handler.dispatchMessage(Handler.java:102)
[MonoDroid] at android.os.Looper.loop(Looper.java:135)
[MonoDroid] at android.app.ActivityThread.main(ActivityThread.java:5221)
[MonoDroid] at java.lang.reflect.Method.invoke(Native Method)
[MonoDroid] at java.lang.reflect.Method.invoke(Method.java:372)
[MonoDroid] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
[MonoDroid] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
[bileApp.Android] type=1400 audit(0.0:63): avc: denied { read } for name="mem" dev="debugfs" ino=186278 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:debugfs:s0 tclass=file
[bileApp.Android] type=1400 audit(0.0:64): avc: denied { read } for name="mem" dev="debugfs" ino=186278 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:debugfs:s0 tclass=file
If I do not override OnSaveInstanceState, it still crashes, but it just says "Shutting down VM" in the logs and doesn't break inside Xamarin Studio, then it shows those last 2 lines from whatever bileApp.Android is.
Thinking critically about this, a field called mHandler being null would imply that a Handler of some kind needs to be set. Is this something I should be doing? But I can't determine from the source code what is going on here, and this stack trace is the only visibility I can see into this crash from within Xamarin Studio. Googling for the field name and NullPointerException, or NPEs on OnSaveInstanceState, didn't get me anywhere.
Are there any other special workarounds I need to be doing to use the support v4 FragmentActivity/FragmentManager? Is there any other workaround for using Material design Toolbar on 4.x without having to use the v4 support library?
Thanks in advance! Let me know if you need me to provide anything else. This happens on both a Nexus 5 with 5.0.1 and a BLU Dash Jr with 4.4. Also I tried switching to the Xamarin Beta channel to see if a fix was in the pipeline, and it's the same result.