Android: Dealing with "IllegalStateException: Can not perform this action after onSaveInstanceState"

This one baffled me for a while. I've only noticed this recently on KitKat 4.4 while transitioning some old apps to use fragments and this exception was put onto the table, but it's definitely a good one to have around.

There are a lot of posts asking how to fix this online. One of them suggests filling Bundle outState with some data before calling super.onSaveInstanceState(). I'm not sure what the mentality behind that is, but it doesn't work (even though it's the selected solution). Heck, I'm not even sure if it was tested.

A few of them are even (ignorantly) suggesting you change your FragmentTransaction.commit() call to FragmentTransaction.commitAllowingStateLoss(), and this will only cause you and your users problems in the long run.

172214lzcc8fda3j4qjcj4

This is NOT an ideal solution. You are not fixing the problem, you are hiding it. Don't do it!

Personally, the only place I would only use it is after a bad APK has gone live and you need to get it fixed within the next half-hour. Once the temporary hot-fix is out, take the time to fix it properly and then remove commitAllowingStateLoss().

Why is it happening?

In essence, what happens is the timing of your FragmentActivity vs Fragment/DialogFragment code allows information to be lost because they all share a common onSaveInstanceState() .

There is a great post by Alex Lockwood titled "Fragment Transactions & Activity State Loss" which explains the whole thing a lot better than I ever could.

Fixing it

The exception is a tricky one to trace down, but at least the stack trace will give you an indication of where it was generated.

In my case, I had a "open file" activity which returned a result to the main activity. Within MainActivity.onActivityResult(), I validated the file type and then immediately displayed a DialogFragment if it was an unrecognised format.

The onSaveInstanceInstanceState() was called during the activity switching, and then sometime during the DialogFragment.show() process the exception was triggered.

Code before:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}

switch(requestCode) {
case ACTIVITY_CHOOSE_FILE: {
// ...

if (!checkOk(data)) {
// Calling this from onActivityResult() gives this exception
// Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
// Because Activity result calls DialogFragment.show() from openFile().
openFile(data);
}
}
}
}

Rather than displaying the DialogFragment immediately, I put a slight delay in my onActivityResult() code using a thread in order to prevent the error.

Code after:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}

switch(requestCode) {
case ACTIVITY_CHOOSE_FILE: {
// ...

if (!checkOk(data)) {
// Shift the call to a thread
new Thread(new Runnable() {
@Override
public void run() {
// Then bump it back onto the UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
openFile(data);
}
});
}
}).start();
}
}
}
}

In effect, the end result is the same and runs fine on all versions of Android without any noticeable delays.

Hate it when small things like this catch you out. These exceptions may be annoying, but they prevent you from randomly losing data by making it painfully obvious that you done goofed.

Sources

Frustration after reading many unhelpful (suggesting to use commitAllowingStateLoss) posts on StackOverflow. Here are some examples:

Canon: Installing PhotoStitch without the a CD

In the past year I've been doing just fine my new computer which doesn't have a CD drive.

Well, until today that is. Canon's PhotoStitch software is pretty good, but you can't actually get it without using the disc that came with the camera! This is a bit of a pain...

IMG_20140106_000711
Camera? Check. CD? Check. Camera case and box? Double check! I'm legit, don't taze me bro.

That was until I found a little registry hack which tricked it into thinking you had the software already installed!

Download Canon's PhotoStitch 3.1.23 Updater for Windows here.

Now you'll have time to create the registry file in order for the updater to work.

Creating the registry

  • Open up Notepad and paste in the following chunk of text. The text you paste depends on your version of Windows!

 

If you're using Windows 7 32bit (x86)...

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\EOS Utility]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\DPP]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\ZoomBrowser EX]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\PhotoStitch]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\EOS Capture]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\EOSViewerUtility]
[HKEY_LOCAL_MACHINE\SOFTWARE\Canon\ODSK]

If you're using Windows 7 64bit (x64)...

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\EOS Utility]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\DPP]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\ZoomBrowser EX]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\ZoomBrowser EX\Settings]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\ZoomBrowser EX\Install]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\PhotoStitch]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\EOS Capture]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\EOSViewerUtility]
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Canon\ODSK]

 

  • Now click File > Save to save the file to your desktop.
  • For the filename, save it as "canon.reg"
  • And for the "Save as file type", change it to "All files (*.*)"
  • Now to go your desktop, double click the file and apply it.
  • Extract and run the PhotoStitch updater
  • Enjoy!

3dtYJLd.gifPq1rhr4s0o1_400 
Boom! Now it "just works"!

Sources

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog