J'en ai un TransactionTooLargeException
. Non reproduisible. Dans les documents, il est dit
La transaction Binder a échoué car elle était trop importante.
Lors d'un appel de procédure distante, les arguments et la valeur de retour de l'appel sont transférés en tant qu'objets Parcel stockés dans le tampon de transaction Binder. Si les arguments ou la valeur de retour sont trop grands pour tenir dans le tampon de transaction, l'appel échouera et TransactionTooLargeException sera levée.
...
Il existe deux résultats possibles lorsqu'un appel de procédure distante lève TransactionTooLargeException. Soit le client n'a pas pu envoyer sa demande au service (très probablement si les arguments étaient trop volumineux pour tenir dans le tampon de transaction), soit le service n'a pas pu renvoyer sa réponse au client (très probablement si la valeur de retour était trop grand pour tenir dans le tampon de transaction).
...
Quelque part, je passe ou reçois des arguments qui dépassent une limite inconnue. Où?
Le stacktrace ne montre rien d'utile:
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)
Cela semble lié aux vues? Quel est le lien avec l'appel de procédure à distance?
Peut-être important: version Android: 4.0.3, appareil: HTC One X
Réponses:
J'ai rencontré ce problème et j'ai constaté que lorsqu'il y avait une énorme quantité de données échangées entre un service et une application (cela implique le transfert de nombreuses miniatures). En fait, la taille des données était d'environ 500 Ko et la taille du tampon de transaction IPC est définie sur 1024 Ko. Je ne sais pas pourquoi il a dépassé le tampon de transaction.
Cela peut également se produire lorsque vous passez beaucoup de données via des extras d'intention
Lorsque vous obtenez cette exception dans votre application, veuillez analyser votre code.
Comment gérer lorsque vous obtenez cette exception
Si possible, divisez la grande opération en petits morceaux, par exemple, au lieu d'appeler applyBatch () avec 1000 opérations, appelez-la avec 100 chacune.
N'échangez pas de données volumineuses (> 1 Mo) entre les services et l'application
Je ne sais pas comment faire cela, mais ne demandez pas à Android, qui peut renvoyer d'énormes données :-)
la source
getInstalledApplications
. Que peut-on faire pour résoudre ce problème?Si vous devez rechercher la parcelle à l'origine de votre incident , vous devriez envisager d'essayer TooLargeTool .
(J'ai trouvé cela comme un commentaire de @Max Spencer sous la réponse acceptée et cela a été utile dans mon cas.)
la source
bundle.clear()
Ce n'est pas une réponse définitive, mais cela peut éclairer les causes d'un
TransactionTooLargeException
problème et aider à identifier le problème.Bien que la plupart des réponses se réfèrent à de grandes quantités de données transférées, je vois cette exception être levée accidentellement après un défilement et un zoom intensifs et l'ouverture répétée d'un menu spinner ActionBar. Le crash se produit en appuyant sur la barre d'action. (il s'agit d'une application de cartographie personnalisée)
Les seules données transmises semblent être des contacts du «répartiteur d'entrée» à l'application. Je pense que cela ne peut raisonnablement pas se situer à près de 1 Mo dans le "tampon de transaction".
Mon application fonctionne sur un appareil quadricœur à 1,6 GHz et utilise 3 threads pour le levage lourd, en gardant un core libre pour le thread d'interface utilisateur. En outre, l'application utilise android: largeHeap, dispose de 10 Mo de tas inutilisés et de 100 Mo d'espace disponible pour agrandir le tas. Je ne dirais donc pas que c'est un problème de ressources.
Le crash est toujours immédiatement précédé de ces lignes:
Qui ne sont pas nécessairement imprimés dans cet ordre, mais (pour autant que je vérifie) se produisent sur la même milliseconde.
Et la trace de pile elle-même, pour plus de clarté, est la même que dans la question:
En fouillant dans le code source d'Android on trouve ces lignes:
frameworks / base / core / jni / android_util_Binder.cpp:
Pour moi, il semble que je frappe peut-être cette fonctionnalité non documentée, où la transaction échoue pour d'autres raisons qu'une transaction étant TooLarge. Ils auraient dû le nommer
TransactionTooLargeOrAnotherReasonException
.Pour l'instant, je n'ai pas résolu le problème, mais si je trouve quelque chose d'utile, je mettrai à jour cette réponse.
mise à jour: il s'est avéré que mon code a divulgué certains descripteurs de fichiers, dont le nombre est maximisé sous linux (généralement 1024), et cela semble avoir déclenché l'exception. C'était donc un problème de ressources après tout. J'ai vérifié cela en ouvrant
/dev/zero
1024 fois, ce qui a entraîné toutes sortes d'exceptions étranges dans les actions liées à l'interface utilisateur, y compris l'exception ci-dessus, et même certains SIGSEGV. Apparemment, l'échec de l'ouverture d'un fichier / socket n'est pas quelque chose qui est géré / signalé très proprement dans Android.la source
Le
TransactionTooLargeException
nous a été qui sévit pendant environ 4 mois maintenant, et nous avons enfin résolu le problème!Ce qui se passait, c'est que nous utilisons un
FragmentStatePagerAdapter
dans unViewPager
. L'utilisateur feuilleterait et créerait plus de 100 fragments (c'est une application de lecture).Bien que nous gérions correctement les fragments dans
destroyItem()
, dans la mise en œuvre d'Androids,FragmentStatePagerAdapter
il y a un bogue, où il a gardé une référence à la liste suivante:Et lorsque Android
FragmentStatePagerAdapter
tentera de sauvegarder l'état, il appellera la fonctionComme vous pouvez le voir, même si vous gérez correctement les fragments de la
FragmentStatePagerAdapter
sous - classe, la classe de base stockera toujours unFragment.SavedState
pour chaque fragment jamais créé. LeTransactionTooLargeException
se produirait lorsque ce tableau était transféré vers unparcelableArray
et que le système d'exploitation ne l'aimerait pas plus de 100 éléments.Par conséquent, le correctif pour nous était de remplacer la
saveState()
méthode et de ne rien stocker pour"states"
.la source
@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; }
Pour ceux qui ont été amèrement déçus à la recherche d'une réponse expliquant pourquoi TransactionTooLargeException apparaît, essayez de vérifier la quantité d'informations que vous enregistrez dans l'état de l'instance.
Sur compile / targetSdkVersion <= 23, nous n'avons qu'un avertissement interne sur la grande taille de l'état enregistré, mais rien ne plante:
Mais sur compile / targetSdkVersion> = 24, nous avons un véritable crash RuntimeException dans ce cas:
Que faire?
Enregistrez les données dans la base de données locale et conservez uniquement les identifiants dans l'état d'instance que vous pouvez utiliser pour récupérer ces données.
la source
Cette exception est généralement levée lorsque l'application est envoyée en arrière-plan.
J'ai donc décidé d'utiliser la méthode Fragment de données pour contourner complètement le
onSavedInstanceStae
cycle de vie. Ma solution gère également des états d'instance complexes et libère de la mémoire dès que possible.J'ai d'abord créé un simple segment pour stocker les données:
Ensuite, lors de mon activité principale, je contourne complètement le cycle d'instance enregistré et reporte la responsabilité à mon fragment de données. Pas besoin de l'utiliser sur les Fragments eux-mêmes, car leur état s'ajoute automatiquement à l'état de l'Activité):
Il ne reste plus qu'à faire éclater l'instance enregistrée:
Détails complets: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/
la source
onSavedState()
, ce qui se produit dans de nombreux cas. Le changement de configuration en est un. Changer d'application et passer en arrière-plan en sont une autre. Et il y en a plus.Il n'y a pas de cause spécifique à ce problème, pour moi, dans ma classe Fragment, je faisais ceci:
au lieu de cela:
la source
Il est important de comprendre que le tampon de transaction est limité à 1 Mo, quelles que soient les capacités de l'appareil ou l'application. Ce tampon est utilisé avec tous les appels d'API que vous effectuez et est partagé entre toutes les transactions qu'une application exécute actuellement.
Je crois qu'il contient également un objet spécifique comme des colis et autres
(Parcel.obtain())
, il est donc important de toujours faire correspondre chacunobtain()
avec unrecycle()
.Cette erreur peut facilement se produire lors d'appels d'API renvoyant un grand nombre de données, même si les données retournées sont inférieures à 1 Mo (si d'autres transactions sont toujours en cours d'exécution).
Par exemple, l'
PackageManager.getInstalledApplication()
appel renvoie une liste de toutes les applications installées. L'ajout de drapeaux spécifiques permet de récupérer un grand nombre de données supplémentaires. Cela pourrait échouer, il est donc recommandé de ne pas récupérer de données supplémentaires et de les récupérer par application.Cependant, l'appel peut toujours échouer, il est donc important de l'entourer d'un
catch
et de pouvoir réessayer si nécessaire.Pour autant que je sache, il n'y a pas de solution à ce problème, sauf en réessayant et en veillant à récupérer le moins d'informations possible.
la source
Moi aussi, j'ai eu cette exception sur un Samsung S3. Je soupçonne 2 causes profondes,
Utilisez DDMS et regardez votre tas pendant que vous jouez votre application, cela vous donnera une indication sur quel setcontentview crée le problème.
J'ai copié tous les drawables dans tous les dossiers pour se débarrasser du problème 2.
Le problème est résolu.
la source
Ajoutez ceci à votre activité
Cela fonctionne pour moi j'espère aussi que cela vous aidera
la source
onCreate()
?Donc, pour nous, nous essayions d'envoyer un objet trop volumineux via notre interface AIDL à un service distant. La taille de la transaction ne peut pas dépasser 1 Mo. La demande est décomposée en blocs séparés de 512 Ko et envoyée une par une via l'interface. Une solution brutale que je connais mais bon - son Android :(
la source
Vous avez effacé votre ancien InstanceState de la méthode onSaveInstanceState , et cela fonctionnera bien. J'utilise FragmentStatePagerAdapter pour mon viewpager donc je reste en dessous de la méthode Override dans mon activité parent pour effacer InstanceState.
J'ai trouvé cette solution ici android.os.TransactionTooLargeException sur Nougat
la source
Récemment, j'ai également rencontré un cas intéressant en travaillant avec le fournisseur de contacts d'Android .
Je devais charger des photos de contacts à partir de la base de données de contacts internes et selon l'architecture du système, toutes ces données sont fournies par des requêtes au fournisseur de contacts.
Comme cela fonctionne comme une application distincte - toutes sortes de transferts de données sont effectués en utilisant le mécanisme Binder et donc le tampon Binder entre en jeu ici.
Ma principale erreur a été de ne pas fermer les
Cursor
données blob obtenues auprès du fournisseur de contacts, de sorte que la mémoire allouée au fournisseur a augmenté et cela a gonflé le tampon du classeur jusqu'à ce que!!!FAILED BINDER TRANSACTION!!!
j'obtienne des tonnes de messages dans ma sortie LogCat.L'idée principale est donc que lorsque vous travaillez avec des fournisseurs de contenu externes et que vous les obtenez
Cursor
, fermez-les toujours lorsque vous avez fini de travailler avec eux.la source
J'ai été confronté au même problème lorsque j'ai essayé d'envoyer un bitmap via Intent et en même temps, quand il s'est produit, j'ai plié l'application.
Comment il est décrit dans cet article entrez la description du lien ici, cela se produit lorsqu'une activité est en train de s'arrêter, cela signifie que l'activité essayait d'envoyer ses bundles d'état enregistrés au système d'exploitation pour les conserver en toute sécurité pour la restauration plus tard (après un changement de configuration) ou traiter la mort) mais qu'un ou plusieurs des paquets envoyés étaient trop volumineux.
Je l'ai résolu via hack en remplaçant onSaveInstanceState dans mon activité:
et commenter appeler super. C'est un hack sale mais cela fonctionne parfaitement. Bitmap a été envoyé avec succès sans se bloquer. J'espère que cela aidera quelqu'un.
la source
Dans mon cas, j'obtiens TransactionTooLargeException comme un incident secondaire après que la bibliothèque native s'est écrasée avec SIGSEGV. Le crash de la bibliothèque native n'est pas signalé, donc je ne reçois que TransactionTooLargeException.
la source
J'ai obtenu ceci dans mon syncadapter en essayant de vracInsert un grand ContentValues []. J'ai décidé de le réparer comme suit:
la source
Pour moi, c'était aussi le
FragmentStatePagerAdapter
, mais le dépassementsaveState()
n'a pas fonctionné. Voici comment je l'ai corrigé:Lorsque vous appelez le
FragmentStatePagerAdapter
constructeur, conservez une liste distincte de fragments dans la classe et ajoutez une méthode pour supprimer les fragments:Ensuite
Activity
, enregistrez laViewPager
position et appelezadapter.removeFragments()
dans leonSaveInstanceState()
méthode :Enfin, dans la
onResume()
méthode substituée , réinstanciez l'adaptateur s'il ne l'est pasnull
. (Si c'est le casnull
, alors leActivity
est ouvert pour la première fois ou après que l'application a été supprimée par Android, dans laquelleonCreate
la création de l'adaptateur sera effectuée.)la source
Assurez-vous que vous ne placez pas dans Intent des données d'objet de grande taille. Dans mon cas, j'ajoutais une taille de chaîne de 500 k, puis je commençais une autre activité. Il a toujours échoué avec cette exception. J'ai évité de partager des données entre les activités en utilisant des variables statiques d'activités - vous n'avez pas à les envoyer à Intent, puis à en tirer.
Ce que j'avais:
la source
Lorsque je traite avec
WebView
dans mon application, cela se produit. Je pense que c'est lié auxaddView
ressources de l'interface utilisateur. Dans mon application, j'ajoute du codeWebViewActivity
comme celui-ci ci-dessous, puis il fonctionne correctement:la source
J'ai trouvé la cause profonde de cela (nous avons eu à la fois "l'ajout de la fenêtre a échoué" et la fuite du descripteur de fichier comme le dit mvds).
Il y a un bogue dans
BitmapFactory.decodeFileDescriptor()
Android 4.4. Il se produit uniquement lorsqueinPurgeable
etinInputShareable
deBitmapOptions
sont définis surtrue
. Cela provoque de nombreux problèmes dans de nombreux endroits interagissent avec les fichiers.Notez que la méthode est également appelée depuis
MediaStore.Images.Thumbnails.getThumbnail()
.Universal Image Loader est concerné par ce problème. Picasso et Glide ne semblent pas affectés. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020
la source
Cette seule ligne de code dans la méthode writeToParcel (Parcel dest, int flags) m'a aidé à me débarrasser de TransactionTooLargeException.
Après ce code, j'écris toutes les données sur l'objet parcelle, c'est-à-dire dest.writeInt (), etc.
la source
Essayez d'utiliser
EventBus
ou d'ContentProvider
aimer la solution.Si vous êtes dans le même processus (normalement, toutes vos activités le seraient), essayez d'utiliser
EventBus
, car l'échange de données en cours n'a PAS besoin d'un tampon, donc vous n'avez pas à vous soucier de la taille de vos données. (Vous pouvez simplement utiliser l'appel de méthode pour transmettre des données, et EventBus cache les choses laides) Voici le détail:Si les deux côtés de l'intention ne sont pas dans le même processus, essayez un peu
ContentProvider
.Voir TransactionTooLargeException
la source
J'ai reçu une TransactionTooLargeException à partir d'une erreur Stackoverflow dans un test Android Espresso. J'ai trouvé la trace de la pile d'erreur stackoverflow dans les journaux lorsque j'ai retiré le filtre Logcat pour mon application.
Je suppose que Espresso a provoqué la TransactionTooLargeException lors de la tentative de gestion d'une trace de pile d'exceptions vraiment importante.
la source
On peut utiliser:
dans le manifeste Android sous la balise d'application.
Cela a résolu le problème dans mon cas!
la source
onSaveInstantState
à des activités / fragments et à l'enregistrement de grandes listes), cela n'a pas aidé.J'ai également été confronté à ce problème pour les données bitmap passant d'une activité à une autre, mais je fais une solution en transformant mes données en données statiques et cela fonctionne parfaitement pour moi
En activité d'abord:
et en deuxième activité:
la source
Cela se produisait dans mon application parce que je passais une liste de résultats de recherche dans les arguments d'un fragment, en attribuant cette liste à une propriété du fragment - qui est en fait une référence au même emplacement en mémoire indiqué par les arguments du fragment - puis en ajoutant de nouveaux éléments dans la liste, ce qui a également modifié la taille des arguments du fragment. Lorsque l'activité est suspendue, la classe de fragment de base tente d'enregistrer les arguments du fragment dans onSaveInstanceState, qui se bloque si les arguments sont supérieurs à 1 Mo. Par exemple:
La solution la plus simple dans ce cas était d'attribuer une copie de la liste à la propriété du fragment au lieu d'attribuer une référence:
Une solution encore meilleure serait de ne pas faire circuler autant de données dans les arguments.
Je n'aurais probablement jamais trouvé cela sans l'aide de cette réponse et de TooLargeTool .
la source
J'ai également vécu TransactionTooLargeException. Tout d'abord, j'ai travaillé à comprendre où cela se produit. Je connais la raison pour laquelle cela se produit. Chacun de nous le sait grâce au contenu volumineux. Mon problème était comme ça et j'ai résolu. Peut-être que cette solution peut être utile à n'importe qui. J'ai une application qui récupère le contenu de l'API. J'obtiens le résultat de l'API dans le premier écran et l'envoie au deuxième écran. Je peux envoyer ce contenu au deuxième écran avec succès. Après le deuxième écran, si je veux passer au troisième écran, cette exception se produit. Chacun de mes écrans est créé à partir de Fragment. Je l'ai remarqué lorsque je quitte le deuxième écran. Il enregistre le contenu de son bundle. si ce contenu est trop volumineux, cette exception se produit. Ma solution est après avoir obtenu le contenu du bundle, je l'efface.
la source
Une solution consisterait à ce que l'application écrive la ArrayList (ou tout autre objet à l'origine du problème) dans le système de fichiers, puis transmette une référence à ce fichier (par exemple, nom de fichier / chemin d'accès) via l'intention au IntentService, puis laisse le IntentService récupérer le contenu du fichier et le reconvertir en ArrayList.
Lorsque IntentService a terminé avec le fichier, il doit le supprimer ou transmettre l'instruction à l'application via une diffusion locale pour supprimer le fichier qu'il a créé (en renvoyant la même référence de fichier qui lui a été fournie).
Pour plus d'informations, voir ma réponse à ce problème connexe .
la source
Comme Intents, les fournisseurs de contenu, Messenger, tous les services système comme le téléphone, le vibreur, etc. utilisent le fournisseur d'infrastructure IPC de Binder. De plus, les rappels du cycle de vie de l'activité utilisent également cette infrastructure.
1 Mo est la limite globale de toutes les transactions de liant exécutées dans le système à un moment particulier.
Dans le cas où de nombreuses transactions se produisent lorsque l'intention est envoyée, elles peuvent échouer même si les données supplémentaires ne sont pas volumineuses. http://codetheory.in/an-overview-of-android-binder-framework/
la source
Avec autant d'endroits où TransactionTooLargeException peut se produire - voici une autre nouveauté pour Android 8 - un crash lorsque quelqu'un commence simplement à taper dans un EditText si le contenu est trop gros.
Il est lié à AutoFillManager (nouveau dans l'API 26) et au code suivant dans
StartSessionLocked()
:Si je comprends bien, cela appelle le service de remplissage automatique - en passant AutofillManagerClient dans le classeur. Et lorsque le EditText a beaucoup de contenu, il semble provoquer le TTLE.
Quelques choses peuvent l'atténuer (ou ont fait comme je
android:importantForAutofill="noExcludeDescendants"
le testais de toute façon): Ajoutez la déclaration de disposition XML d'EditText. Ou en code:Une deuxième solution de contournement terrible et terrible pourrait également être de remplacer les méthodes
performClick()
etonWindowFocusChanged()
pour détecter l'erreur dans une sous-classe TextEdit elle-même. Mais je ne pense pas que ce soit vraiment sage ...la source