0

I am having a TransactionTooLargeException when I close/minimize my app. I am assuming it is due to my Bundle being too large (3 JSONArrays as strings), but it would be great if someone can diagnose more information from my error trace.

Here it is:

05-28 17:17:25.994 9518-9518/com.adamtrudeauarcaro.godbuilder E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 551100)
05-28 17:17:25.996 9518-9518/com.adamtrudeauarcaro.godbuilder D/AndroidRuntime: Shutting down VM
05-28 17:17:25.998 9518-9518/com.adamtrudeauarcaro.godbuilder E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                Process: com.package.godbuilder, PID: 9518
                                                                                java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 551100 bytes
                                                                                    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4211)
                                                                                    at android.os.Handler.handleCallback(Handler.java:751)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                    at android.os.Looper.loop(Looper.java:154)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:6688)
                                                                                    at java.lang.reflect.Method.invoke(Native Method)
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
                                                                                 Caused by: android.os.TransactionTooLargeException: data parcel size 551100 bytes
                                                                                    at android.os.BinderProxy.transactNative(Native Method)
                                                                                    at android.os.BinderProxy.transact(Binder.java:628)
                                                                                    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:4132)
                                                                                    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4203)
                                                                                    at android.os.Handler.handleCallback(Handler.java:751) 
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                                    at android.os.Looper.loop(Looper.java:154) 
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:6688) 
                                                                                    at java.lang.reflect.Method.invoke(Native Method) 
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 
Adam Arcaro
  • 451
  • 7
  • 19
  • I think that comes from `onSaveInstanceState()`, though I am far from certain. – CommonsWare May 28 '17 at 21:22
  • @CommonsWare I do not have that method defined, could the error still be caused by the implicit implementation? – Adam Arcaro May 28 '17 at 21:26
  • If you had some huge text in an EditText, perhaps. It is unlikely, IMHO. – CommonsWare May 28 '17 at 21:40
  • @CommonsWare I have ArrayList contains 10 to 20 images in form of base64 and showing it in recycler view but on minimizing app crashing due to same reason as mentioned in question. what could be the solution? – Zaid Mirza Jun 01 '19 at 11:05
  • @ZaidMirza: Do not put those images in the saved instance state `Bundle` and do not pass them between activities using `Intent` extras. Use a single-activity architecture (with fragments for your different screens) and use `ViewModel` for holding onto those images across configuration changes. If you need those images in multiple screens, use a shared `ViewModel`. – CommonsWare Jun 01 '19 at 11:29
  • @CommonsWare not putting anything on saved instance. It seems like system is trying to save fragment and its data so that it could be restore later when user resume it by coming back to app from recent app screen or any other way – Zaid Mirza Jun 01 '19 at 12:06
  • 1
    @ZaidMirza: Correct. However, there is a limit for how much space you can consume that way, and you are exceeding that limit. If you have data that needs to survive your app's process being terminated, store it on disk. – CommonsWare Jun 01 '19 at 12:10
  • @CommonsWare yes you are right but problem is how we can save our data to disk when user press home button and clear recycler view source list so that it couldn't be saved by system. what could be appropriate callback ? OnSaveInstance? (Mine data size is 2.15MB and Im aware of that 1MB is limit) – Zaid Mirza Jun 01 '19 at 12:14
  • @ZaidMirza: "how we can save our data to disk when user press home button" -- you don't. You save the data when you get the data. I am guessing that you are downloading these images. If so, you should be using a image-loading library with a disk cache option (e.g., Glide, Picasso). Even if for some reason you cannot, once you have downloaded the image, use a background thread to save it to your own cache. – CommonsWare Jun 01 '19 at 12:18
  • @CommonsWare yes I cannot use Glide or Picasso because its an complex Json response of 2.15MB and Im using Retrofit to get data and it cache response by default I guess. According to you, in Simple words "I should cache service response on disk". But again, data would be in ArrayList while showing on screen. So I also need to clear ArrayList because its holding all 2.15MB of data. – Zaid Mirza Jun 01 '19 at 12:27
  • 1
    @ZaidMirza: The `ArrayList` will not go into the `Bundle` by magic. It will only go into the `Bundle` if *you put it in the `Bundle`*. So, do not put it in the `Bundle`. – CommonsWare Jun 01 '19 at 12:28
  • I've answered a similar question here: https://stackoverflow.com/a/73008611/2860701 – Alberto Jul 17 '22 at 01:12

2 Answers2

5

From your error trace it doesn't say, but I can tell you from experience certainly that this happens when your bundle is too large to store it as a saved instance state. Which means that when you minimize the app, it tries to call onSaveInstanceState and your bundle is storing more data than the supported by the system.

droidpl
  • 5,872
  • 4
  • 35
  • 47
  • Awesome, I just needed some confirmation that this was the issue before changing my design. Thanks! – Adam Arcaro May 28 '17 at 21:27
  • No problem, you can also find almost the amount allowed in this post: https://stackoverflow.com/questions/12496700/maximum-length-of-intent-putextra-method-force-close – droidpl May 28 '17 at 21:28
0

I encountered this exception before too. The scenario is we pass paths of all pictures or videos in album through Bundle to preview fragment, usually it is OK, but it becomes a problem when there are thousands of files in user's device. The exception will be thrown when activity stops and application is reclaimed by system, during which the argument data are passed to system through binder for restore later. Here is the exception trace: 

Thread Name: 'main' Back traces starts. java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 2352912 bytes at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:263) at android.app.ActivityThread.main(ActivityThread.java:8246) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006) Caused by: android.os.TransactionTooLargeException: data parcel size 2352912 bytes at android.os.BinderProxy.transactNative(Native Method) at android.os.BinderProxy.transact(BinderProxy.java:568) at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4429) at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145) ... 7 more Back traces ends.

To fix it, we restraint only one hundred paths around the current clicked picture or video. Here are the codes.

    val selections = ArrayList<Selection>()
    // The number of pictures in user device can be more than 1000.
    // Restrict the list size to fix TransactionTooLargeException: data parcel size too large.
    val interval = 100
    val start: Int = max(0, position - interval / 2)
    val end: Int = min(materials.size - 1, start + interval)
    for (i in start..end) {
        val albumItem: IAlbumItem = materials[i]
        val selection = Selection(Triple("null", i, -1), Pair(-1, -1), albumItem)
        selection.what = what
        selections.add(selection)
    }

    val bundle = Bundle()
    // The collection has changed, the position should offset the same too.
    bundle.putLong("limitVideoDuration", limitVideoDuration)
    bundle.putInt("position", position - start)
    bundle.putSerializable("selections", selections)
Saint
  • 1,492
  • 1
  • 11
  • 20