Qué hacer en TransactionTooLargeException

Tengo una pista de error de una aplicación TransactionTooLargeException. No reproducible y nunca antes. En los documentos dice

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

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

Hay dos resultados posibles cuando una llamada a procedimiento remoto arroja TransactionTooLargeException. O bien el cliente no pudo enviar su solicitud al servicio (muy probablemente si los argumentos eran demasiado grandes para caber en el búfer de transacción), o el servicio no pudo enviar su respuesta de vuelta al cliente (muy probablemente si el valor de retorno era demasiado grande para caber en el búfer de transacción).

Así que, de acuerdo, en algún lugar que estoy pasando o recibiendo argumentos que exceden algún límite desconocido. ¿Pero donde?

La stacktrace no muestra nada de mis archivos:

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, porque todas las líneas de Ventana / Vista? ¿Cómo se relaciona esto con la llamada a procedimiento remoto? ¿Cómo puedo buscar el motivo de este error?

En la aplicación, estoy utilizando solo servicios web, no estoy utilizando la clase de servicio, ¿los servicios web son las “llamadas a procedimientos remotos” o qué más podría ser …?

Gracias por adelantado…

PD Tal vez es importante: Versión de Android: 4.0.3, Dispositivo: HTC One X

Encontré este problema y descubrí que cuando se intercambiaba una gran cantidad de datos entre un servicio y una aplicación (esto implica transferir muchas miniaturas). En realidad, el tamaño de los datos fue de alrededor de 500 kb, y el tamaño del búfer de transacción de IPC está establecido en 1024 KB. No estoy seguro de por qué excedió el buffer de transacción.

Esto también puede ocurrir cuando pasas muchos datos a través de extras

Cuando obtenga esta excepción en su aplicación, analice su código.

  1. ¿Estás intercambiando muchos datos entre tus servicios y tu aplicación?
  2. Al utilizar intenciones para compartir datos enormes, (por ejemplo, el usuario selecciona una gran cantidad de archivos de la galería compartir compartir en la prensa, los URI de los archivos seleccionados se transferirán usando intenciones)
  3. recibir archivos de bitmap del servicio
  4. esperando a que Android responda con enormes datos (por ejemplo, getInstalledApplications () cuando el usuario instaló muchas aplicaciones)
  5. utilizando applyBatch () con muchas operaciones pendientes

Cómo manejar cuando obtienes esta excepción

Si es posible, divida la operación grande en fragmentos pequeños, por ejemplo, en lugar de llamar a applyBatch () con 1000 operaciones, llámelo con 100 cada uno.

No intercambie datos enormes (> 1 MB) entre los servicios y la aplicación

No sé cómo hacer esto, pero, no consulte con Android, que puede devolver datos enormes 🙂

Esta no es una respuesta definitiva, pero puede arrojar algo de luz sobre las causas de una TransactionTooLargeException y ayudar a identificar el problema.

Aunque la mayoría de las respuestas se refieren a grandes cantidades de datos transferidos, veo que esta excepción se lanza accidentalmente después de un desplazamiento pesado y un acercamiento y abriendo varias veces un menú giratorio ActionBar. El locking ocurre al tocar la barra de acciones. (esta es una aplicación de mapeo personalizada)

Los únicos datos que se transmiten parecen ser toques del “Despachador de entrada” a la aplicación. Creo que esto no puede suponer razonablemente cerca de 1 mb en el “Buffer de transacción”.

Mi aplicación se ejecuta en un dispositivo cuádruple de 1,6 GHz y utiliza 3 subprocesos para heavylifting, manteniendo un núcleo libre para el subproceso de interfaz de usuario. Además, la aplicación usa android: largeHeap, tiene 10 mb de montón sin usar a la izquierda y tiene 100 mb de espacio restante para hacer crecer el montón. Entonces no diría que es un problema de recursos.

El locking siempre está precedido inmediatamente por estas líneas:

 W/InputDispatcher( 2271): channel ~ Consumer closed input channel or an error occurred. events=0x9 E/InputDispatcher( 2271): channel ~ Channel is unrecoverably broken and will be disposed! E/JavaBinder(28182): !!! FAILED BINDER TRANSACTION !!! 

Que no necesariamente se imprimen en ese orden, pero (según comprobé) ocurren en el mismo milisegundo.

Y la stack se traza a sí misma, para mayor claridad, es la misma que en la pregunta:

 E/AndroidRuntime(28182): java.lang.RuntimeException: Adding window failed .. E/AndroidRuntime(28182): Caused by: android.os.TransactionTooLargeException 

Profundizando en el código fuente de Android uno encuentra estas líneas:

frameworks / base / core / jni / android_util_Binder.cpp:

 case FAILED_TRANSACTION: ALOGE("!!! FAILED BINDER TRANSACTION !!!"); // TransactionTooLargeException is a checked exception, only throw from certain methods. // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION // but it is not the only one. The Binder driver can return BR_FAILED_REPLY // for other reasons also, such as if the transaction is malformed or // refers to an FD that has been closed. We should change the driver // to enable us to distinguish these cases in the future. jniThrowException(env, canThrowRemoteException ? "android/os/TransactionTooLargeException" : "java/lang/RuntimeException", NULL); 

Para mí, parece que estoy golpeando esta característica no documentada, donde la transacción falla por otras razones que una transacción sea demasiado grande. Deberían haberlo llamado TransactionTooLargeOrAnotherReasonException .

En este momento no resolví el problema, pero si encuentro algo útil, actualizaré esta respuesta.

actualización: resultó que mi código se filtró algunos descriptores de archivos, cuyo número se maximiza en Linux (por lo general, 1024), y esto parece haber desencadenado la excepción. Entonces, fue un problema de recursos después de todo. Lo verifiqué abriendo /dev/zero 1024 veces, lo que dio lugar a todo tipo de excepciones raras en las acciones relacionadas con la interfaz de usuario, incluida la excepción anterior e incluso algunos SIGSEGV. Aparentemente, la falla al abrir un archivo / socket no es algo que se maneje / informe de manera muy limpia en todo Android.

¡La TransactionTooLargeException ha estado afectando por aproximadamente 4 meses, y finalmente hemos resuelto el problema!

Lo que sucedía era que estamos usando un FragmentStatePagerAdapter en una ViewPager . El usuario pasaría la página y crearía más de 100 fragmentos (es una aplicación de lectura).

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

 private ArrayList mSavedState = new ArrayList(); 

Y cuando el FragmentStatePagerAdapter de Android intente guardar 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 

Como puede ver, incluso si gestiona adecuadamente los fragmentos en la subclase FragmentStatePagerAdapter , la clase base aún almacenará un Fragment.SavedState para cada uno de los fragmentos creados. La TransactionTooLargeException ocurriría cuando esa matriz se plotbleArray un plotbleArray y al sistema operativo no le gustaría más de 100 elementos.

Por lo tanto, la solución para nosotros era anular el método saveState() y no almacenar nada 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; } 

Para aquellos que amargamente se decepcionaron en la búsqueda de respuestas sobre por qué aparece TransactionTooLargeException, intente verificar lo que guarda en el estado de la instancia.

En compile / targetSdkVersion <= 23 tenemos solo una advertencia interna sobre el tamaño grande del estado guardado, pero nada se colgó:

 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 compile / targetSdkVersion> = 24 tenemos caída 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 conserve solo los identificadores en el estado de la instancia que puede usar para recuperar estos datos.

Si necesita investigar qué paquete está causando su falla, debería considerar probar TooLargeTool .

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

No hay una causa específica de este problema. Para mí, en mi clase Fragmento estaba haciendo esto:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View rootView = inflater.inflate(R.layout.snacks_layout, container); //<-- notice the absence of the false argument return rootView; } 

en lugar de esto:

 View rootView = inflater.inflate(R.layout.softs_layout, container, false); 

Yo también obtuve esta excepción en un Samsung S3. Sospecho que hay 2 causas raíz

  1. tienes mapas de bits que cargan y ocupan demasiada memoria, usa reducción de tamaño
  2. Le faltan algunos elementos extraíbles de las carpetas dibujables-_dpi, Android los busca en dibujables y los redimensiona, haciendo que su setContentView salte repentinamente y use mucha memoria.

Use DDMS y mire su montón mientras juega su aplicación, que le dará alguna indicación sobre qué setcontentview está creando el problema.

Copié todos los dibujables en todas las carpetas para deshacerme del problema 2.

Informaré en unos días lo que encuentre.

Es importante comprender que el búfer de transacción está limitado a 1 MB, independientemente de las capacidades o aplicaciones del dispositivo. Este búfer se utiliza con cada llamada API que realice y se comparte entre todas las transacciones que se está ejecutando actualmente.

Creo que también contiene algunos objetos específicos, como plots y similares (Parcel.obtain()) , por lo que es importante que siempre coincida cada obtain() con un recycle() .

Este error puede ocurrir fácilmente en llamadas de API que devuelven una gran cantidad de datos, aunque los datos devueltos sean de menos de 1 MB (si otras transacciones aún se están ejecutando).

Por ejemplo, la llamada PackageManager.getInstalledApplication() devuelve una lista de todas las aplicaciones instaladas. Agregar banderas específicas permite recuperar una gran cantidad de datos adicionales. Si lo hace, es probable que falle, por lo que se recomienda no recuperar ningún dato adicional y recuperarlos por aplicación.

Sin embargo, la llamada aún puede fallar, por lo que es importante rodearlo con una catch y poder volver a intentarlo si es necesario.

Por lo que yo sé, no existe una solución alternativa a tal problema, excepto volver a intentar y asegurarse de recuperar la menor cantidad de información posible.

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

Por lo tanto, he decidido utilizar el método Fragment de datos para eludir por completo el ciclo de vida onSavedInstanceStae . Mi solución también maneja estados de instancia complejos y libera memoria lo antes posible.

Primero, creé 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 elude por completo el ciclo de la instancia guardada y difiero la respoinsibilty a mi Fragmento de datos. No es necesario usar esto en los 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.com/avoiding-transactiontoolargeexception-on-android-nougat-and-up/

Entonces para nosotros fue que intentamos enviar un objeto demasiado grande a través de nuestra interfaz AIDL a un servicio remoto. El tamaño de la transacción no puede exceder 1MB. La solicitud se divide en trozos separados de 512 KB y se envía de uno en uno a través de la interfaz. Una solución brutal que conozco pero bueno, es Android 🙁

Recientemente también me he encontrado con un caso interesante mientras trabajaba con el proveedor de contactos de Android.

Necesitaba cargar fotos de contactos desde la base de datos de contactos internos y de acuerdo con la architecture del sistema, todos estos datos son entregados por consultas al Proveedor de Contactos.

Como funciona como una aplicación separada, todos los tipos de transferencia de datos se realizan utilizando el mecanismo Binder y, por lo tanto, el búfer Binder entra en juego aquí.

Mi principal error fue que no cerré el Cursor con los datos de blobs obtenidos del Proveedor de Contactos, por lo que la memoria asignada para el proveedor aumentó y esto infló el búfer de Binder hasta que recibí toneladas de !!!FAILED BINDER TRANSACTION!!! mensajes en mi salida LogCat.

Por lo tanto, la idea principal es que cuando trabaje con proveedores de contenido externos y obtenga Cursor de ellos, siempre ciérrelo cuando termine de trabajar con ellos.

En mi caso, recibo TransactionTooLargeException como un locking secundario después de que la biblioteca nativa se estrelló con SIGSEGV. El locking de la biblioteca nativa no se informa, por lo que solo recibo TransactionTooLargeException.

Asegúrese de no poner datos de objetos de Intención de gran tamaño. En mi caso, estaba agregando tamaño String 500k y luego comencé otra actividad. Siempre falló con esta excepción. Evité compartir datos entre actividades mediante el uso de variables estáticas de actividades: no tienes que enviarlos a Intención y luego extraer de ellos.

Lo que tuve:

 String html = new String();//some string of 500K data. Intent intent = new Intent(MainActivity.this, PageWebView.class); //this is workaround - I just set static variable and then access it from another activity. MainActivity.htmlBody = timelineDb.getHTMLBodyForTweet(tweet); //This line was present and it actually failed with the same exception you had. //intent.putExtra("com.gladimdim.offtie.webview", html); 

Lo obtuve en mi adaptador syncadapter al tratar de insertar de forma masiva un gran ContentValues ​​[]. Decidí arreglarlo de la siguiente manera:

 try { count = provider.bulkInsert(uri, contentValueses); } catch (TransactionTooLarge e) { int half = contentValueses.length/2; count += provider.bulkInsert(uri, Arrays.copyOfRange(contentValueses, 0, half)); count += provider.bulkInsert(uri, Arrays.copyOfRange(contentValueses, half, contentValueses.length)); } 

Encontré la causa raíz de esto (obtuvimos la “ventana de adición fallida” y la fuga del descriptor de archivo como dice mvds).

Hay un error en BitmapFactory.decodeFileDescriptor() de Android 4.4. Solo se produce cuando inPurgeable y inInputShareable of BitmapOptions se establecen en true . Esto causa muchos problemas en muchos lugares para interactuar con los archivos.

Tenga en cuenta que el método también se llama desde MediaStore.Images.Thumbnails.getThumbnail() .

Universal Image Loader se ve afectado por este problema. Picasso y Glide parece que no se ven afectados. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020

Para mí también era el FragmentStatePagerAdapter , sin embargo, la anulación de saveState() no funcionó. Así es como lo arreglé:

Cuando llame al constructor FragmentStatePagerAdapter , mantenga una lista separada de fragmentos dentro de la clase y agregue un método para eliminar los fragmentos:

 class PagerAdapter extends FragmentStatePagerAdapter { ArrayList items; PagerAdapter(ArrayList frags) { super(getFragmentManager()); //or getChildFragmentManager() or getSupportFragmentManager() this.items = new ArrayList<>(); this.items.addAll(frags); } public void removeFragments() { Iterator iter = items.iterator(); while (iter.hasNext()) { Fragment item = iter.next(); getFragmentManager().beginTransaction().remove(item).commit(); iter.remove(); } notifyDataSetChanged(); } } //...getItem() and etc methods... } 

Luego, en la Activity , guarde la posición de ViewPager y llame a un dapter.removeFragments() en el método onSaveInstanceState() anulado:

 private int pagerPosition; @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); //save other view state here pagerPosition = mViewPager.getCurrentItem(); adapter.removeFragments(); } 

Por último, en el método onResume() reemplazado, vuelva a crear una instancia del adaptador si no es null . (Si es null , la Activity se abrirá por primera vez o después de que Android haya eliminado la aplicación, en la que onCreate realizará la creación del adaptador).

 @Override public void onResume() { super.onResume(); if (adapter != null) { adapter = new PagerAdapter(frags); mViewPager.setAdapter(adapter); mViewPager.setCurrentItem(currentTabPosition); } } 

Una solución sería que la aplicación escriba ArrayList (o cualquier objeto que esté causando el problema) en el sistema de archivos, luego pase una referencia a ese archivo (por ejemplo, nombre de archivo / ruta) a través del Intent a IntentService y luego deje que IntentService recuperar el contenido del archivo y convertirlo a una ArrayList.

Cuando IntentService ha terminado con el archivo, debe eliminarlo o pasar la instrucción a la aplicación a través de una Transmisión local para eliminar el archivo que creó (devolviendo la misma referencia de archivo que se le suministró).

Para obtener más información, consulte mi respuesta a este problema relacionado .

Como Intents, Proveedores de contenido, Messenger, todos los servicios del sistema como Telephone, Vibrator, etc. utilizan el proveedor de infraestructura IPC de Binder. Además, las devoluciones de llamada del ciclo de vida de la actividad también usan esta infraestructura.

1 MB es el límite general de todas las transacciones de enlace ejecutadas en el sistema en un momento determinado.

En caso de que haya muchas transacciones que suceden cuando se envía el bash, puede fallar aunque los datos adicionales no sean grandes. http://codetheory.in/an-overview-of-android-binder-framework/

Cuando trato con WebView en mi aplicación, sucede. Creo que está relacionado con los recursos addView y UI. En mi aplicación agrego algún código en WebViewActivity como este a continuación, luego se ejecuta correctamente:

 @Override protected void onDestroy() { if (mWebView != null) { ((ViewGroup) mWebView.getParent()).removeView(mWebView); mWebView.removeAllViews(); mWebView.destroy(); } super.onDestroy(); } 

Con tantos lugares donde puede suceder TransactionTooLargeException – aquí hay uno más nuevo en Android 8 – un locking cuando alguien simplemente comienza a escribir en un EditText si el contenido es demasiado grande.

Está relacionado con AutoFillManager (nuevo en API 26) y el siguiente código en StartSessionLocked() :

  mSessionId = mService.startSession(mContext.getActivityToken(), mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), mCallback != null, flags, mContext.getOpPackageName()); 

Si entiendo correctamente, esto llama al servicio de autocompletar, pasando el AutofillManagerClient dentro del encuadernador. Y cuando EditText tiene mucho contenido, parece causar el TTLE.

Algunas cosas pueden mitigarlo (o lo hicieron como estaba probando de todos modos): agregue android:importantForAutofill="noExcludeDescendants" en la statement de diseño xml de EditText. O en el código:

 EditText et = myView.findViewById(R.id.scriptEditTextView); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { et.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); } 

Una segunda y terrible solución también podría ser anular los performClick() y onWindowFocusChanged() para detectar el error en una subclase de TextEdit. Pero no creo que eso sea sabio realmente …

Para mí, TransactionTooLargeException se produjo cuando intenté enviar una imagen de bitmap grande de una actividad a otra a través de un bash. Resolví este problema usando las variables globales de la aplicación .

Por ejemplo, si desea enviar una imagen grande de bitmap de una actividad A a una actividad B , entonces almacene esa imagen de bitmap en una variable global

 ((Global) this.getApplication()).setBitmap(bitmap); 

luego comienza la actividad B y lee de la variable global

 Bitmap bitmap = ((Global) this.getApplication()).getBitmap(); 

Tuve el mismo problema al transferir (enviar difusión) un objeto de bitmap a un receptor de difusión.

 intent.putExtra("image", bitmapImage); 

Entonces, en lugar de enviarlos como bitmap. Convertí el bitmap en matriz de bytes. ¡¡¡Para mi sorpresa, funcionó!!! Me pregunto por qué Android no permite transferir datos enormes con Bitmap, pero permite el mismo a través de matriz de bytes.

  intent.putExtra("imageInByteArray", convertBitmapToByteArray(bitmapImage)); 

En el receptor, convertí la matriz de bytes a bitmap y esto resolvió mi problema.

Esta única línea de código en el método writeToParcel (Parcel dest, int flags) me ayudó a deshacerme de TransactionTooLargeException.

 dest=Parcel.obtain(); 

Después de este código solo estoy escribiendo todos los datos en el objeto del paquete, es decir, dest.writeInt (), etc.

Intenta utilizar EventBus o ContentProvider como solución.

Si está en el mismo proceso (normalmente todas sus actividades serían), intente utilizar EventBus , porque en el proceso el intercambio de datos NO necesita un buffer, por lo que no debe preocuparse de que sus datos sean demasiado grandes. (Puede utilizar la llamada a método para pasar datos de hecho, y EventBus esconder las cosas feas) Aquí está el detalle:

 // one side startActivity(intentNotTooLarge); EventBus.getDefault().post(new FooEvent(theHugeData)); // the other side @Subscribe public void handleData(FooEvent event) { /* get and handle data */ } 

Si los dos lados de Intent no están en el mismo proceso, pruebe un poco ContentProvider .


Consulte TransactionTooLargeException

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

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

Me enfrenté al mismo problema cuando traté de enviar bitmap a través de Intent y al mismo tiempo, cuando doblé la aplicación.

Cómo se describe en este artículo ingrese la descripción del enlace aquí sucede cuando una Actividad está en proceso de detención, eso significa que la Actividad estaba tratando de enviar sus paquetes de estado guardados al sistema operativo del sistema para su posterior restauración (después de un cambio de configuración) o procesar la muerte) pero que uno o más de los Bundles que envió eran demasiado grandes.

Lo resolví mediante hack anulando onSaveInstanceState en mi actividad:

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

y comentar llamada super. Es un truco sucio pero está funcionando perfectamente. Bitmap fue enviado exitosamente sin fallas. Espero que esto ayude a alguien.

Obtuve una TransactionTooLargeException de un error Stackoverflow en una prueba de Android Espresso. Encontré el seguimiento de la stack de errores de stackoverflow en los registros cuando quité el filtro de Logcat para mi aplicación.

Supongo que Espresso causó TransactionTooLargeException al tratar de manejar una stack de excepción muy grande.

Tiene claro su antiguo InstanceState del método onSaveInstanceState , y funcionará bien. Estoy usando FragmentStatePagerAdapter para mi viewpager, por lo que mantengo el método Override debajo en mi actividad principal para InstanceState claro.

 @Override protected void onSaveInstanceState(Bundle InstanceState) { super.onSaveInstanceState(InstanceState); InstanceState.clear(); } 

Encontré esta solución desde aquí android.os.TransactionTooLargeException en Nougat

Uno puede usar:

 android:largeHeap="true" 

en Android Manifiesto bajo etiqueta de aplicación.

¡Esto resolvió el problema en mi caso!

También me enfrentaba a este problema para el paso de datos de Bitmap de una actividad a otra, pero hago una solución al convertir mis datos en datos estáticos y esto funciona perfectamente para mí

En actividad primero:

 public static Bitmap bitmap_image; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); bitmap_image=mybitmap; } 

and in second activity :

  @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Bitmap mybitmap=first.bitmap_image; } 

Another possible cause:

I had an activity that was starting itself in onResume() ! This results in a ton of transactions and causes the phone (Galaxy S2) to completely freeze (no ANR or anything) and then to hard reset, which is kind of a huge bug in itself.

It would be interesting to see what happens on other phones with this code:

 class MyActivity extends Activity { // ... @Override void onResume() { super.onResume() startActivity(new Intent(this, MyActivity.class)); } }