I was testing my app on Android Nougat, and it crashed when I try to move from one Activity to another. I saw this in the log: java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 700848 bytes
.
Actually, the platform has been printing warning log about this for a while, but let's be honest, who has time to read all the logs? Nougat (API 24) throws TransactionTooLargeException
s as RuntimeException
s, so we cannot ignore that any more.
onSaveInstanceState
Turns out I was saving a big list of search results during onSaveInstanceState
to persist them over rotation. Time to move that to a Loader!
But what is the limit?
But now I'm curious: What is the limit? I wrote a sample app to find out.
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = new Intent(this, AnotherActivity.class); startActivity(intent); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); int length = 1000; Uri uri = getIntent().getData(); if (uri != null) { try { length = Integer.parseInt(uri.getLastPathSegment()); } catch (NumberFormatException e) { } } byte[] data = new byte[length]; outState.putByteArray("data", data); } }
To try different sizes, I start the app like this:
adb shell am start \ -a android.intent.action.View \ -n com.sqisland.tutorial.transcation_too_large/.MainActivity \ -d 700000
This launches MainActivity
, which immediately goes to AnotherActivity
. When that happens, the system calls onSaveInstanceState
, which tries to stash away a byte array of the length specified in the adb command, retrieved by getIntent().getData()
. This way, I can try different numbers without recompiling and redeploying the app.
I did a binary search on a Nougat emulator and my Nexus 9. The limit is slightly different, but it hovers around 500000. That is not a small number, but not too hard to exceed if you try to store data rather than state.