0

I noticed that there are a lot of exceptions reported in Google Console:

java.lang.RuntimeException: 
  at android.app.servertransaction.PendingTransactionActions$StopInfo.run (PendingTransactionActions.java:160)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:201)
  at android.app.ActivityThread.main (ActivityThread.java:6815)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:873)
Caused by: android.os.TransactionTooLargeException: 
  at android.os.BinderProxy.transactNative (BinderProxy.java)
  at android.os.BinderProxy.transact (BinderProxy.java:1131)
  at android.app.IActivityManager$Stub$Proxy.activityStopped (IActivityManager.java:3973)
  at android.app.servertransaction.PendingTransactionActions$StopInfo.run (PendingTransactionActions.java:144)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:201)
  at android.app.ActivityThread.main (ActivityThread.java:6815)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:873)

I'm trying to figure out what is throwing that exception, but I can't. The only suspicious thing I have in my source coude is a part in which I'm loading a very big json file (7MB), parsing it to a model (data object) with GSON, and passing it throught a handler to my activity:

Message msg = new Message();
msg.what = Util.THREAD_DATA_GENERATED;
msg.obj = data;
handler.sendMessage(msg);

. . .

notifyHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        Data data = (Data) msg.obj;
        Manager.getInstance().setData(data);
        showSelectTeamDialog();
        return true;
    }
});

Can this handler throw that exception when passing a msg.obj parameter with a big size?

NullPointerException
  • 36,107
  • 79
  • 222
  • 382

1 Answers1

0

A handler wont. But sending that data via an Intent to an Activity can. The data is serialized for possible cross-process messaging, and there's a data size limit (at one time it was 2MB, unsure if that's changed). I would bet that showSelectTeamDialog is launching an Activity to show the dialog, and that's what's failing.

Look at the stack trace. It included:

at android.app.IActivityManager$Stub$Proxy.activityStopped (IActivityManager.java:3973)

So the activity was stopped for some reason. The only reason that would happen is if finish was called, or if another activity was launched. So we're definitely seeing too much data in an Intent here.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • I'm using putSerializable to put a small portion of the data into the dialog, but that portion is just 1/9 of the total size of the model. Whould that crash the application? – NullPointerException Feb 06 '20 at 19:46
  • Possibly? I may be wrong and the allowed size may be smaller. An Intent is backed by a Bundle, but I think the size isn't checked until the intent is actually sent somewhere. It would be the sending, not the adding of data that causes the exception. Which is why putSerializable isn't in the stack trace. The error isn't detected until the activity/service tries to launch. – Gabe Sechan Feb 06 '20 at 19:49
  • what a crazy thing, I will need to create a singleton for sharing data between activities whithout crashes. I remember the times with C when you were able to pass the reference of an object instead of the full object. This is a big fail of android and java. – NullPointerException Feb 06 '20 at 19:53
  • My recollection is that the transaction size limit is 512KB on modern Android OS levels. Additionally, these transactions are used by more clients than just you, so you should really try to keep what you put in them very small. It sounds like you might want to write your json to disk and then send a file path instead of the actual data (and then load the data from disk on the other side). – Ben P. Feb 06 '20 at 19:55
  • Documentation (https://developer.android.com/reference/android/os/TransactionTooLargeException) says the current limit is 1MB, but for some reason I feel strongly that I've read it's actually smaller than that. Maybe whatever I read was just recommending only 50% utilization in order to leave space in the shared transaction for other clients. – Ben P. Feb 06 '20 at 19:56
  • thanks @BenP. but writing and reading from disk whould be super slow, I think it's a much better option to use a singleton to share the reference without serializing it. It's a uggly solution, but it's much faster and efficient – NullPointerException Feb 06 '20 at 19:58
  • @NullPointerException Its not a fail on Android, its a usecase it supports that limits it. The activity being launched may be in another app. That means it can't share the data as a reference- different processes don't share memory. – Gabe Sechan Feb 07 '20 at 00:12