Qué hacer en TransactionTooLargeException

11 minutos de lectura

Que hacer en
Usuario

Recibí una TransactionTooLargeException. No reproducible. En los documentos dice

La transacción de Binder falló porque era demasiado grande.

Durante una llamada a un procedimiento remoto, los argumentos y el valor de retorno de la llamada se transfieren como objetos Parcel almacenados en el búfer de transacciones de Binder. Si los argumentos o el valor devuelto son demasiado grandes para caber en el búfer de transacciones, la llamada fallará y se lanzará una excepción TransactionTooLargeException.

Hay dos resultados posibles cuando una llamada a un procedimiento remoto arroja una TransactionTooLargeException. El cliente no pudo enviar su solicitud al servicio (muy probablemente si los argumentos eran demasiado grandes para caber en el búfer de transacciones) o el servicio no pudo enviar su respuesta al cliente (muy probablemente si el valor de retorno fue demasiado grande para caber en el búfer de transacciones).

Entonces, en algún lugar estoy pasando o recibiendo argumentos que exceden un límite desconocido. ¿Donde?

El stacktrace no muestra nada útil:

java.lang.RuntimeException: Adding window failed
at android.view.ViewRootImpl.setView(ViewRootImpl.java:548)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
... 16 more
android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

¿Parece estar relacionado con las vistas? ¿Cómo se relaciona esto con la llamada a procedimiento remoto?

Quizás importante: Versión de Android: 4.0.3, Dispositivo: HTC One X

  • No. Pero no lo entendí de nuevo. Tenga un rastreador de errores en la aplicación en vivo y lo obtuve solo esta vez en aproximadamente 3 semanas. Al menos no parece que suceda con frecuencia. Tal vez valga la pena abrir un problema en Android, aunque…

    – Usuario

    10 de agosto de 2012 a las 18:31

  • No tengo una respuesta, pero esto hace que mi Galaxy S2 se restablezca de manera confiable.

    – Timmmmm

    25 de septiembre de 2012 a las 10:15

  • Acabo de hacer que esto ocurra en una de mis aplicaciones hoy. Esto también solo ha sucedido una vez y con un Galaxy S3. Es interesante que esto solo parece estar aprendiendo con los dispositivos más potentes.

    – danwms

    26 de septiembre de 2012 a las 8:20

  • esa excepción se agregó en API 15, desarrollador.android.com/reference/android/os/… Y lo he reproducido en el MapView mientras me desplazaba por el mapa. hasta que el gc escribió que no me queda memoria (me tomó un par de minutos)

    – meh

    9 de diciembre de 2012 a las 13:45

  • El búfer de transacciones está limitado a 1 MB en todos los dispositivos, y este búfer almacena todas las transacciones. Por lo tanto, cuanto más potente sea el dispositivo, más transacciones podrá realizar simultáneamente, todas las cuales consumen el mismo búfer de 1 MB. Dicho esto, su respuesta no es una respuesta sino un comentario.

    – 3c71

    23 de noviembre de 2013 a las 16:21


Si necesita investigar qué Parcel está causando su bloqueo, debería considerar intentar Demasiado grandeHerramienta.

(Encontré esto como un comentario de @Max Spencer en la respuesta aceptada y fue útil en mi caso).

  • La solución más infravalorada. Esta herramienta lo ayuda a reducir las actividades ofensivas

    – Kedar Paranjape

    7 de junio de 2018 a las 14:26

  • esta herramienta es para kotlin:/ ¿alguna alternativa para java?

    – maxwellnewage

    25 de junio de 2019 a las 16:09

  • @maxwellnewage: parece que la última versión (0.2.1, 0.2.0 también) está actualmente no funciona en aplicaciones solo Java. Tuve que usar la versión 0.1.6 y funcionó bien entonces

    – danny

    16 de enero de 2020 a las 17:56


  • Al usar esta herramienta, detecto que estaba usando paquetes de gran tamaño en mis fragmentos. Lo que hice fue extraer el argumento del paquete y borrar el paquete usando bundle.clear()

    – EJ Chathuranga

    24 de mayo de 2020 a las 19:17

  • Esta herramienta también me ayudó. El motivo de TransactionTooLargeException fue pasar parámetros de gran tamaño para fragmentarlos en argumentos (usando Bundle). Ahora paso parámetros para fragmentar en el constructor, y todo funciona bien.

    – Máximo

    30 de julio de 2020 a las 10:00


1646966774 557 Que hacer en
iko_wp

los TransactionTooLargeException nos ha estado molestando durante aproximadamente 4 meses, ¡y finalmente hemos resuelto el problema!

Lo que estaba pasando era que estábamos usando un FragmentStatePagerAdapter en un ViewPager. El usuario buscaría y crearía más de 100 fragmentos (es una aplicación de lectura).

Aunque gestionamos correctamente los fragmentos en destroyItem()en la implementación de Android de FragmentStatePagerAdapter hay un error, donde mantuvo una referencia a la siguiente lista:

private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();

Y cuando el Android FragmentStatePagerAdapter intenta salvar el estado, llamará a la función

@Override
public Parcelable saveState() {
    Bundle state = null;
    if (mSavedState.size() > 0) {
        state = new Bundle();
        Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
        mSavedState.toArray(fss);
        state.putParcelableArray("states", fss);
    }
    for (int i=0; i<mFragments.size(); i++) {
        Fragment f = mFragments.get(i);
        if (f != null && f.isAdded()) {
            if (state == null) {
                state = new Bundle();
            }
            String key = "f" + i;
            mFragmentManager.putFragment(state, key, f);
        }
    }
    return state;
}

Como puede ver, incluso si administra correctamente los fragmentos en el FragmentStatePagerAdapter subclase, la clase base seguirá almacenando una Fragment.SavedState por cada fragmento jamás creado. los TransactionTooLargeException ocurriría cuando esa matriz se volcara a un parcelableArray y al sistema operativo no le gustaría más de 100 elementos.

Por lo tanto, la solución para nosotros fue anular el saveState() método y no almacenar cualquier cosa para "states".

@Override
public Parcelable saveState() {
    Bundle bundle = (Bundle) super.saveState();
    bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out
    return bundle;
}

  • De todas las posibilidades para esto, para mí esta parecía la única opción. ¿Qué se almacena en el estado que le permitiría llegar a este tamaño? Si el estado es tan necesario que existe un código para guardarlo, ¿cómo es posible que esto no cause otros problemas? Gracias

    -Kenny

    24 de noviembre de 2017 a las 15:48

  • @Override public Parcelable saveState() { Bundle bundle = (Bundle) super.saveState(); if (bundle != null) { Parcelable[] states = bundle.getParcelableArray("states"); // Subset only last 3 states if (states != null) states = Arrays.copyOfRange(states, states.length > 3 ? states.length - 3 : 0, states.length - 1); bundle.putParcelableArray("states", states); } else bundle = new Bundle(); return bundle; }

    – Ramy Sabry

    21 de febrero de 2018 a las 12:20


  • Solo dejo los últimos 3 estados, verifique el código anterior.

    – Ramy Sabry

    21 de febrero de 2018 a las 12:24

  • Después de usar su solución, también guarda datos en “estados”

    – pavel

    2 de marzo de 2018 a las 9:50

  • Enfrenté el mismo problema con ViewPager2 y FragmentStateAdapter. El problema aquí es FragmentStateAdapter marcado como ‘saveState()’ como final y la clase ViewPager2 también es final, por lo que no podemos anular los métodos. sin embargo, pude deshacerme del problema Transaction demasiado grande al agregar \android:saveEnabled=”false” ‘ en la entrada XML para View pager

    – Desarrollador

    15 de marzo de 2021 a las 13:44


Para aquellos que se sintieron amargamente decepcionados al buscar una respuesta de por qué aparece la excepción TransactionTooLargeException, intente verificar cuánta información guarda en el estado de la instancia.

en compilar/targetSdkVersion <= 23 solo tenemos una advertencia interna sobre el gran tamaño del estado guardado, pero nada se bloquea:

E/ActivityThread: App sent too much data in instance state, so it was ignored
    android.os.TransactionTooLargeException: data parcel size 713856 bytes
    at android.os.BinderProxy.transactNative(Native Method)
    at android.os.BinderProxy.transact(Binder.java:615)
    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3604)
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3729)
    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:6044)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

Pero en compilar/targetSdkVersion >= 24 tenemos un bloqueo real de RuntimeException en este caso:

java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 713860 bytes
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3737)
    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:6044)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
 Caused by: android.os.TransactionTooLargeException: data parcel size 713860 bytes
   at android.os.BinderProxy.transactNative(Native Method)
   at android.os.BinderProxy.transact(Binder.java:615)
   at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3604)
   at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3729)
   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:6044) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

¿Qué hacer?

Guarde los datos en la base de datos local y mantenga solo las identificaciones en el estado de instancia que puede usar para recuperar estos datos.

  • De todas las posibilidades para esto, para mí esta parecía la única opción. ¿Qué se almacena en el estado que le permitiría llegar a este tamaño? Si el estado es tan necesario que existe un código para guardarlo, ¿cómo es posible que esto no cause otros problemas? Gracias

    -Kenny

    24 de noviembre de 2017 a las 15:48

  • @Override public Parcelable saveState() { Bundle bundle = (Bundle) super.saveState(); if (bundle != null) { Parcelable[] states = bundle.getParcelableArray("states"); // Subset only last 3 states if (states != null) states = Arrays.copyOfRange(states, states.length > 3 ? states.length - 3 : 0, states.length - 1); bundle.putParcelableArray("states", states); } else bundle = new Bundle(); return bundle; }

    – Ramy Sabry

    21 de febrero de 2018 a las 12:20


  • Solo dejo los últimos 3 estados, verifique el código anterior.

    – Ramy Sabry

    21 de febrero de 2018 a las 12:24

  • Después de usar su solución, también guarda datos en “estados”

    – pavel

    2 de marzo de 2018 a las 9:50

  • Enfrenté el mismo problema con ViewPager2 y FragmentStateAdapter. El problema aquí es FragmentStateAdapter marcado como ‘saveState()’ como final y la clase ViewPager2 también es final, por lo que no podemos anular los métodos. sin embargo, pude deshacerme del problema Transaction demasiado grande al agregar \android:saveEnabled=”false” ‘ en la entrada XML para View pager

    – Desarrollador

    15 de marzo de 2021 a las 13:44


Esta excepción generalmente se lanza cuando la aplicación se envía a un segundo plano.

Así que he decidido utilizar el método Fragmento de datos para eludir por completo el onSavedInstanceStae ciclo vital. Mi solución también maneja estados de instancia complejos y libera memoria lo antes posible.

Primero he creado un Fargment simple para almacenar los datos:

package info.peakapps.peaksdk.logic;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;

/**
 * A neat trick to avoid TransactionTooLargeException while saving our instance state
 */

public class SavedInstanceFragment extends Fragment {

    private static final String TAG = "SavedInstanceFragment";
    private Bundle mInstanceBundle = null;

    public SavedInstanceFragment() { // This will only be called once be cause of setRetainInstance()
        super();
        setRetainInstance( true );
    }

    public SavedInstanceFragment pushData( Bundle instanceState )
    {
        if ( this.mInstanceBundle == null ) {
            this.mInstanceBundle = instanceState;
        }
        else
        {
            this.mInstanceBundle.putAll( instanceState );
        }
        return this;
    }

    public Bundle popData()
    {
        Bundle out = this.mInstanceBundle;
        this.mInstanceBundle = null;
        return out;
    }

    public static final SavedInstanceFragment getInstance(FragmentManager fragmentManager )
    {
        SavedInstanceFragment out = (SavedInstanceFragment) fragmentManager.findFragmentByTag( TAG );

        if ( out == null )
        {
            out = new SavedInstanceFragment();
            fragmentManager.beginTransaction().add( out, TAG ).commit();
        }
        return out;
    }
}

Luego, en mi Actividad principal, eludo el ciclo de la instancia guardada por completo y defiendo la responsabilidad a mi Fragmento de datos. No es necesario usar esto en los propios Fragmentos, ya que su estado se agrega automáticamente al estado de la Actividad):

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    SavedInstanceFragment.getInstance( getFragmentManager() ).pushData( (Bundle) outState.clone() );
    outState.clear(); // We don't want a TransactionTooLargeException, so we handle things via the SavedInstanceFragment
}

Lo que queda es simplemente abrir la instancia guardada:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(SavedInstanceFragment.getInstance(getFragmentManager()).popData());
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState( SavedInstanceFragment.getInstance( getFragmentManager() ).popData() );
}

Todos los detalles: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/

  • ¿Qué sucede si la actividad se destruye cuando la aplicación está en segundo plano y tratas de ponerla en primer plano?

    – Maestro Desastre

    1 oct 2017 a las 8:56

  • @MasterDisaster en ese caso, no se guarda ningún estado porque el proceso que contiene el fragmento de instancia ha muerto.

    – Vaiden

    1 de octubre de 2017 a las 9:24

  • Rights, por lo que este caso solo funciona con cambio de configuración.

    – Maestro Desastre

    2 de octubre de 2017 a las 11:12

  • Funciona cada vez que se activa el sistema operativo onSavedState(), que sucede en muchos casos. El cambio de configuración es uno. Cambiar de aplicación y pasar al fondo son otros. Y hay más

    – Vaiden

    2 oct 2017 a las 13:41

  • Creo que esta solución debería expandirse para guardar datos de diferentes fuentes. Probablemente un HashMap con etiquetas como claves y paquetes como valores.

    – CoolMind

    20 de diciembre de 2018 a las 15:53

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad