Tengo una TransactionTooLargeException
. No reproducible. 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 transacciones de Binder. Si los argumentos o el valor de retorno son demasiado grandes para caber en el búfer de transacciones, la llamada fallará y se lanzará TransactionTooLargeException.
...
Hay dos resultados posibles cuando una llamada a procedimiento remoto arroja TransactionTooLargeException. O 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 era demasiado grande para caber en el búfer de transacciones).
...
Entonces, en algún lugar estoy pasando o recibiendo argumentos que exceden algún límite desconocido. ¿Dónde?
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
Respuestas:
Encontré este problema y descubrí que cuando se intercambia 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 era de alrededor de 500 kb, y el tamaño del búfer de transacciones IPC se establece en 1024 KB. No estoy seguro de por qué excedió el búfer de transacciones.
Esto también puede ocurrir cuando pasa muchos datos a través de intentos adicionales
Cuando reciba esta excepción en su aplicación, analice su código.
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 una.
No intercambie grandes datos (> 1 MB) entre servicios y aplicaciones
No sé cómo hacer esto, pero, no consultes Android, que puede devolver datos enormes :-)
fuente
getInstalledApplications
. ¿Qué se puede hacer para resolver esto?Si necesita investigar qué paquete está causando su bloqueo, debería considerar probar TooLargeTool .
(Encontré esto como un comentario de @Max Spencer debajo de la respuesta aceptada y fue útil en mi caso).
fuente
bundle.clear()
Esta no es una respuesta definitiva, pero puede arrojar algo de luz sobre las causas de
TransactionTooLargeException
ay 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 produce de manera incidental después de un desplazamiento y un zoom intensos y de abrir repetidamente un menú giratorio de ActionBar. El bloqueo ocurre al tocar la barra de acción. (esta es una aplicación de mapeo personalizada)
Los únicos datos que se transmiten parecen ser toques del "Distribuidor de entrada" a la aplicación. Creo que esto no puede alcanzar razonablemente cerca de 1 mb en el "Transaction Buffer".
Mi aplicación se ejecuta en un dispositivo de cuatro núcleos a 1.6 GHz y usa 3 hilos para levantar pesas, manteniendo un núcleo libre para el hilo de la interfaz de usuario. Además, la aplicación usa android: largeHeap, le quedan 10 mb de montón sin usar y le quedan 100 mb de espacio para hacer crecer el montón. Entonces no diría que es un problema de recursos.
El bloqueo siempre está precedido inmediatamente por estas líneas:
Que no necesariamente se imprimen en ese orden, pero (por lo que he comprobado) suceden en el mismo milisegundo.
Y el rastro de la pila en sí mismo, para mayor claridad, es el mismo que en la pregunta:
Profundizando en el código fuente de Android uno encuentra estas líneas:
frameworks / base / core / jni / android_util_Binder.cpp:
Para mí, parece que posiblemente estoy golpeando esta característica indocumentada, donde la transacción falla por otras razones que no son una transacción que es demasiado grande. Deberían haberlo nombrado
TransactionTooLargeOrAnotherReasonException
.En este momento no resolví el problema, pero si encuentro algo útil, actualizaré esta respuesta.
actualización: resultó que mi código filtró algunos descriptores de archivos, cuyo número se maximiza en Linux (generalmente 1024), y esto parece haber desencadenado la excepción. Entonces fue un problema de recursos después de todo. Verifiqué esto abriendo
/dev/zero
1024 veces, lo que resultó en todo tipo de excepciones extrañas en 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.fuente
¡
TransactionTooLargeException
Nos ha estado atormentando durante aproximadamente 4 meses, y finalmente hemos resuelto el problema!Lo que estaba sucediendo es que estamos usando a
FragmentStatePagerAdapter
en aViewPager
. El usuario hojearía y crearía más de 100 fragmentos (es una aplicación de lectura).Aunque administramos los fragmentos correctamente
destroyItem()
, en la implementación de AndroidFragmentStatePagerAdapter
hay un error, donde se mantiene una referencia a la siguiente lista:Y cuando el Android
FragmentStatePagerAdapter
intente salvar el estado, llamará a la funciónComo puede ver, incluso si administra adecuadamente los fragmentos en la
FragmentStatePagerAdapter
subclase, la clase base seguirá almacenando unFragment.SavedState
fragmento por cada fragmento creado. EstoTransactionTooLargeException
ocurriría cuando esa matriz se volcara a ayparcelableArray
el sistema operativo no quisiera tener más de 100 elementos.Por lo tanto, la solución para nosotros fue anular el
saveState()
método y no almacenar nada"states"
.fuente
@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; }
Para aquellos que decepcionaron amargamente en busca de la respuesta de por qué aparece TransactionTooLargeException, intente verificar cuánta información guarda en el estado de instancia.
En compile / targetSdkVersion <= 23 solo tenemos una advertencia interna sobre el gran tamaño del estado guardado, pero nada se bloquea:
Pero en compile / targetSdkVersion> = 24 tenemos un verdadero bloqueo de RuntimeException en este caso:
¿Qué hacer?
Guarde los datos en la base de datos local y mantenga solo las identificaciones en estado de instancia que puede usar para recuperar estos datos.
fuente
Esta excepción generalmente se produce cuando la aplicación se envía en segundo plano.
Así que decidí usar el método Fragmento de datos para eludir completamente el
onSavedInstanceStae
ciclo de vida. 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:
Luego, en mi Actividad principal, eludo completamente el ciclo de instancias guardadas y aplazo la responsabilidad de mi Fragmento de datos. No es necesario usar esto en los Fragmentos mismos, dado que su estado se agrega al estado de la Actividad automáticamente):
Lo que queda es simplemente hacer estallar la instancia guardada:
Detalles completos: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/
fuente
onSavedState()
, lo que sucede en muchos casos. El cambio de configuración es uno. Cambiar de aplicación e ir al fondo es otra. Y hay más.No hay una causa específica de este problema. Para mí, en mi clase Fragment, estaba haciendo esto:
en lugar de esto:
fuente
Es importante comprender que el búfer de transacciones está limitado a 1 MB, independientemente de las capacidades del dispositivo o la aplicación. Este búfer se usa con todas las llamadas API que realiza y se comparte entre todas las transacciones que una aplicación está ejecutando actualmente.
Creo que también contiene algún objeto específico, como parcelas y
(Parcel.obtain())
demás, por lo que es importante hacer coincidir siempre cada unoobtain()
con arecycle()
.Este error puede ocurrir fácilmente en llamadas API que devuelven muchos datos, aunque los datos devueltos sean inferiores a 1 MB (si todavía se están ejecutando otras transacciones).
Por ejemplo, la
PackageManager.getInstalledApplication()
llamada devuelve una lista de todas las aplicaciones instaladas. Agregar banderas específicas permite recuperar muchos 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 rodearla con a
catch
y poder volver a intentarlo si es necesario.Hasta donde yo sé, no hay solución a este problema, excepto volver a intentarlo y asegurarse de recuperar la menor información posible.
fuente
Yo también obtuve esta excepción en un Samsung S3. Sospecho 2 causas raíz,
Use DDMS y mire su montón mientras juega su aplicación, eso le dará alguna indicación sobre qué setcontentview está creando el problema.
Copié todos los dibujos en todas las carpetas para deshacerme del problema 2.
Problema resuelto.
fuente
Agregue esto a su actividad
Funciona para mí, espero que también te ayude
fuente
onCreate()
?Entonces, para nosotros, estábamos tratando de 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 1 MB. La solicitud se divide en fragmentos separados de 512 KB y se envía uno a la vez a través de la interfaz. Una solución brutal que conozco pero bueno, es Android :(
fuente
Ha borrado su antiguo InstanceState del método onSaveInstanceState , y funcionará bien. Estoy usando FragmentStatePagerAdapter para mi visor, así que mantengo debajo del método Override en mi actividad principal para borrar InstanceState.
Encontré esta solución desde aquí android.os.TransactionTooLargeException en Nougat
fuente
Recientemente también me encontré 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 arquitectura del sistema, todos estos datos se entregan mediante 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, por lo que el búfer Binder entra en juego aquí.
Mi error principal fue que no lo hice cerca de la
Cursor
con los datos blob recibido de contactos de proveedores, de manera que la memoria asignada para el proveedor aumentó y esto infla a amortiguar el aglutinante hasta que me dieron un montón de!!!FAILED BINDER TRANSACTION!!!
mensajes en mi salida LogCat.Entonces, la idea principal es que cuando trabajas con proveedores de contenido externos y recibes
Cursor
mensajes de ellos, siempre ciérralo cuando termines de trabajar con ellos.fuente
Me enfrenté al mismo problema cuando intenté enviar un mapa de bits a través de Intent y al mismo tiempo cuando sucedió, 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, lo que significa que la Actividad estaba tratando de enviar sus Paquetes de estado guardados al sistema operativo del sistema para mantenerlos seguros para su restauración más tarde (después de un cambio de configuración o procesar la muerte), pero que uno o más de los paquetes que envió eran demasiado grandes.
Lo resolví a través de un pirateo anulando onSaveInstanceState en mi Actividad:
y comentar llamar super. Es un truco sucio pero funciona perfectamente. El mapa de bits se envió correctamente sin bloqueos. Espero que esto ayude a alguien.
fuente
En mi caso, recibo TransactionTooLargeException como un bloqueo secundario después de que la biblioteca nativa se bloqueó con SIGSEGV. El bloqueo de la biblioteca nativa no se informa, por lo que solo recibo TransactionTooLargeException.
fuente
Obtuve esto en mi adaptador syncadapter cuando intenté insertar en masa un ContentValues grande []. Decidí arreglarlo de la siguiente manera:
fuente
Para mí también fue
FragmentStatePagerAdapter
, sin embargo, la anulaciónsaveState()
no funcionó. Así es como lo arreglé:Al llamar al
FragmentStatePagerAdapter
constructor, mantenga una lista separada de fragmentos dentro de la clase y agregue un método para eliminar los fragmentos:Luego, en el
Activity
, guarde laViewPager
posición y llameadapter.removeFragments()
alonSaveInstanceState()
método anulado :Por último, en el
onResume()
método anulado , vuelva a crear una instancia del adaptador si no lo estánull
. (Si es asínull
,Activity
se abrirá por primera vez o después de que Android elimine la aplicación, lo queonCreate
hará la creación del adaptador).fuente
Asegúrese de no colocar datos de objeto Intent de gran tamaño. En mi caso, agregué String 500k y luego comencé otra actividad. Siempre fallaba con esta excepción. Evité compartir datos entre actividades mediante el uso de variables estáticas de actividades: no es necesario enviarlas a Intent y luego extraerlas.
Lo que tuve
fuente
Cuando estoy tratando con el
WebView
en mi aplicación sucede. Creo que está relacionado con losaddView
recursos de UI. En mi aplicación agrego un códigoWebViewActivity
como este a continuación y luego funciona bien:fuente
Encontré la causa raíz de esto (obtuvimos "error al agregar ventana" y fuga del descriptor de archivo como dice mvds).
Hay un error en
BitmapFactory.decodeFileDescriptor()
Android 4.4. Solo ocurre cuandoinPurgeable
yinInputShareable
deBitmapOptions
se establecen entrue
. Esto causa muchos problemas en muchos lugares interactuar con 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 parecen no verse afectados. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020
fuente
Esta línea de código en el método writeToParcel (Parcel dest, int flags) me ayudó a deshacerme de TransactionTooLargeException.
Después de este código, solo estoy escribiendo todos los datos en el objeto de paquete, es decir, dest.writeInt (), etc.
fuente
Intenta usar
EventBus
o unaContentProvider
solución similar.Si está en el mismo proceso (normalmente todas sus actividades lo harían), intente usarlo
EventBus
, porque el intercambio de datos en el proceso NO necesita un poco de búfer, por lo que no debe preocuparse porque sus datos sean demasiado grandes. (Simplemente puede usar la llamada al método para pasar datos, y EventBus oculta las cosas feas) Aquí está el detalle:Si los dos lados de la intención no están en el mismo proceso, intente un poco
ContentProvider
.Ver TransactionTooLargeException
fuente
Obtuve una TransactionTooLargeException de un error de Stackoverflow en una prueba de Android Espresso. Encontré el seguimiento de pila de error stackoverflow en los registros cuando quité el filtro Logcat para mi aplicación.
Supongo que Espresso causó la TransactionTooLargeException al tratar de manejar un stacktrace de excepción realmente grande.
fuente
Uno puede usar:
en el Manifiesto de Android bajo la etiqueta de la aplicación.
¡Esto resolvió el problema en mi caso!
fuente
onSaveInstantState
a actividades / fragmentos y guardar listas grandes) no ayudó.También estaba enfrentando este problema para los datos de mapa de bits que pasaban de una actividad a otra, pero hago una solución al hacer que mis datos sean datos estáticos y esto funciona perfecto para mí
En actividad primero:
y en segunda actividad:
fuente
Esto estaba sucediendo en mi aplicación porque estaba pasando una lista de resultados de búsqueda en los argumentos de un fragmento, asignando esa lista a una propiedad del fragmento, que en realidad es una referencia a la misma ubicación en la memoria señalada por los argumentos del fragmento, y luego agregué nuevos elementos a la lista, que también cambiaron el tamaño de los argumentos del fragmento. Cuando se suspende la actividad, la clase de fragmento base intenta guardar los argumentos del fragmento en onSaveInstanceState, que se bloquea si los argumentos son mayores de 1 MB. Por ejemplo:
La solución más fácil en este caso fue asignar una copia de la lista a la propiedad del fragmento en lugar de asignar una referencia:
Una solución aún mejor sería no pasar tantos datos en los argumentos.
Probablemente nunca hubiera encontrado esto sin la ayuda de esta respuesta y TooLargeTool .
fuente
También he vivido TransactionTooLargeException. En primer lugar, he trabajado para entender dónde ocurre. Sé la razón por la que ocurre. Todos lo sabemos por su gran contenido. Mi problema era así y lo resolví. Quizás esta solución pueda ser útil para cualquiera. Tengo una aplicación que obtiene contenido de la API. Recibo el resultado de la API en la primera pantalla y lo envío a la segunda pantalla. Puedo enviar este contenido a la segunda pantalla con éxito. Después de la segunda pantalla, si quiero ir a la tercera pantalla, se produce esta excepción. Cada una de mi pantalla se crea a partir de Fragment. Me di cuenta de eso cuando salgo de la segunda pantalla. Guarda su contenido del paquete. Si este contenido es demasiado grande, se produce esta excepción. Mi solución es que después de obtener el contenido del paquete, lo borro.
fuente
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 al IntentService y luego deje el IntentService recuperar el contenido del archivo y convertirlo nuevamente en una ArrayList.
Cuando IntentService haya 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 proporcionó).
Para obtener más información, vea mi respuesta a este problema relacionado .
fuente
Como intenciones, los proveedores de contenido, Messenger, todos los servicios del sistema como teléfono, vibrador, etc. utilizan el proveedor de infraestructura IPC de Binder. Además, las devoluciones de llamada del ciclo de vida de la actividad también utilizan esta infraestructura.
1 MB es el límite general de todas las transacciones de carpeta ejecutadas en el sistema en un momento particular.
En caso de que ocurran muchas transacciones cuando se envía la intención, puede fallar aunque los datos adicionales no sean grandes. http://codetheory.in/an-overview-of-android-binder-framework/
fuente
Con tantos lugares donde TransactionTooLargeException puede ocurrir , aquí hay uno nuevo para Android 8, un bloqueo cuando alguien simplemente comienza a escribir en EditText si el contenido es demasiado grande.
Está relacionado con AutoFillManager (nuevo en API 26) y el siguiente código en
StartSessionLocked()
:Si entiendo correctamente, esto llama al servicio de autocompletar, pasando el AutofillManagerClient dentro del cuaderno. Y cuando EditText tiene mucho contenido, parece causar el TTLE.
Algunas cosas pueden mitigarlo (o hice lo que estaba probando de todos modos): agregue
android:importantForAutofill="noExcludeDescendants"
la declaración de diseño xml de EditText. O en código:Una segunda solución horrible y terrible también podría ser anular los métodos
performClick()
yonWindowFocusChanged()
para detectar el error en una subclase TextEdit. Pero no creo que sea sabio realmente ...fuente