Я получил TransactionTooLargeException
. Не воспроизводится. В документах сказано
Сбой транзакции Binder, поскольку она была слишком большой.
Во время удаленного вызова процедуры аргументы и возвращаемое значение вызова передаются как объекты Parcel, хранящиеся в буфере транзакций Binder. Если аргументы или возвращаемое значение слишком велики, чтобы поместиться в буфере транзакций, вызов завершится неудачно и будет выдано исключение TransactionTooLargeException.
...
Есть два возможных результата, когда удаленный вызов процедуры вызывает TransactionTooLargeException. Либо клиент не смог отправить свой запрос в службу (скорее всего, если аргументы были слишком велики для размещения в буфере транзакций), либо службе не удалось отправить свой ответ обратно клиенту (скорее всего, если возвращаемое значение было слишком большой для размещения в буфере транзакций).
...
Так что где-то я передаю или получаю аргументы, которые превышают какой-то неизвестный предел. Куда?
Трассировка стека не показывает ничего полезного:
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)
Кажется, это связано с мнением? Как это связано с удаленным вызовом процедуры?
Может быть важно: версия Android: 4.0.3, устройство: HTC One X
Ответы:
Я столкнулся с этой проблемой и обнаружил, что при обмене огромным объемом данных между службой и приложением (это включает в себя передачу большого количества миниатюр). На самом деле размер данных составлял около 500 КБ, а размер буфера транзакции IPC был равен 1024 КБ. Я не уверен, почему он превысил буфер транзакций.
Это также может произойти, когда вы передаете много данных через преднамеренные дополнения
Когда вы получите это исключение в вашем приложении, пожалуйста, проанализируйте ваш код.
Как обращаться, когда вы получаете это исключение
Если возможно, разделите большую операцию на маленькие порции, например, вместо вызова applyBatch () с 1000 операциями, вызовите ее с 100 каждой.
Не обменивайтесь огромными данными (> 1 МБ) между службами и приложением
Я не знаю, как это сделать, но, не запрашивайте Android, который может вернуть огромные данные :-)
источник
getInstalledApplications
. Что можно сделать, чтобы решить эту проблему?Если вам нужно выяснить, какая посылка вызывает сбой, попробуйте TooLargeTool .
(Я нашел это как комментарий @Max Spencer под принятым ответом, и это было полезно в моем случае.)
источник
bundle.clear()
Это не окончательный ответ, но он может пролить некоторый свет на причины
TransactionTooLargeException
и помочь определить проблему.Хотя большинство ответов относятся к большим объемам передаваемых данных, я вижу, что это исключение возникает случайно после интенсивной прокрутки и масштабирования и многократного открытия вращающегося меню ActionBar. Сбой происходит при нажатии на панель действий. (это пользовательское картографическое приложение)
Похоже, единственные передаваемые данные касаются приложения «Диспетчер ввода» и приложения. Я думаю, что это не может разумно составить где-то около 1 МБ в «Буфере транзакций».
Мое приложение работает на четырехъядерном устройстве с частотой 1,6 ГГц и использует 3 потока для тяжелой работы, оставляя одно ядро свободным для потока пользовательского интерфейса. Кроме того, приложение использует android: largeHeap, имеет 10 МБ неиспользуемой кучи и 100 МБ оставшегося пространства для роста кучи. Так что я бы не сказал, что это проблема с ресурсами.
Сбою всегда сразу предшествуют следующие строки:
Которые не обязательно печатаются в этом порядке, но (насколько я проверял) происходят в одну и ту же миллисекунду.
И сама трассировка стека, для ясности, такая же, как в вопросе:
Копаясь в исходном коде Android, можно найти следующие строки:
рамки / база / ядро / JNI / android_util_Binder.cpp:
Для меня это звучит так, как будто я использую эту недокументированную функцию, в которой транзакция завершается неудачей по другим причинам, чем транзакция TooLarge. Они должны были назвать это
TransactionTooLargeOrAnotherReasonException
.На данный момент я не решил проблему, но если я найду что-то полезное, я обновлю этот ответ.
обновление: оказалось, что в моем коде просочились некоторые файловые дескрипторы, число которых максимально увеличено в linux (обычно 1024), и это, похоже, вызвало исключение. Так что это была проблема с ресурсом в конце концов. Я подтвердил это, открыв
/dev/zero
1024 раза, что привело к всевозможным странным исключениям в действиях, связанных с пользовательским интерфейсом, включая исключение выше и даже некоторые SIGSEGV. Очевидно, что неудача в открытии файла / сокета - это не то, что обрабатывается / сообщается очень аккуратно в Android.источник
TransactionTooLargeException
Были преследующие нас в течение 4 месяцев, и мы наконец -то решен вопрос!То, что происходило, было, мы используем
FragmentStatePagerAdapter
вViewPager
. Пользователь будет пролистывать и создавать более 100 фрагментов (это приложение для чтения).Несмотря на то, что мы должным образом управляем фрагментами
destroyItem()
, в реализации AndroidFragmentStatePagerAdapter
есть ошибка, в которой содержится ссылка на следующий список:И когда Android
FragmentStatePagerAdapter
попытается сохранить состояние, он вызовет функциюКак видите, даже если вы правильно управляете фрагментами в
FragmentStatePagerAdapter
подклассе, базовый класс все равно будет хранитьFragment.SavedState
для каждого отдельного фрагмента, когда-либо созданного. ЭтоTransactionTooLargeException
произойдет, когда этот массив будет выгружен в a,parcelableArray
и ОС не понравится более 100 элементов.Поэтому исправление для нас было переопределить
saveState()
метод и не хранить ничего для"states"
.источник
@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; }
Для тех, кто сильно разочарован в поисках ответа на вопрос, почему появляется TransactionTooLargeException, попробуйте проверить, сколько информации вы сохранили в состоянии экземпляра.
На compile / targetSdkVersion <= 23 у нас есть только внутреннее предупреждение о большом размере сохраненного состояния, но ничего не происходит:
Но при compile / targetSdkVersion> = 24 мы имеем реальный сбой RuntimeException в этом случае:
Что делать?
Сохраняйте данные в локальной базе данных и сохраняйте только идентификаторы в состоянии экземпляра, которые вы можете использовать для извлечения этих данных.
источник
Это исключение обычно выдается при отправке приложения в фоновом режиме.
Поэтому я решил использовать метод фрагментирования данных, чтобы полностью обойти
onSavedInstanceStae
жизненный цикл. Мое решение также обрабатывает сложные состояния экземпляров и освобождает память как можно скорее.Сначала я создал простой Fargment для хранения данных:
Затем в своей основной Деятельности я полностью обхожу цикл сохраненных экземпляров и переношу ответ на свой фрагмент данных. Нет необходимости использовать это на самих фрагментах, так как их состояние добавляется в состояние действия автоматически):
Осталось просто извлечь сохраненный экземпляр:
Полная информация: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/
источник
onSavedState()
, что происходит во многих случаях. Изменение конфигурации одно. Переключение приложений и переход в фоновый режим - это другое. И это еще не все.Нет конкретной причины этой проблемы. Для меня в моем классе Fragment я делал это:
вместо этого:
источник
Важно понимать, что буфер транзакций ограничен 1 МБ независимо от возможностей устройства или приложения. Этот буфер используется для всех вызовов API, которые вы делаете, и используется всеми транзакциями, которые в данный момент выполняется приложением.
Я считаю, что он также содержит некоторые конкретные объекты, такие как посылки и тому подобное
(Parcel.obtain())
, поэтому важно всегда сопоставлять каждыйobtain()
сrecycle()
.Эта ошибка может легко произойти при вызовах API, возвращающих много данных, даже если возвращаемые данные меньше 1 МБ (если все еще выполняются другие транзакции).
Например,
PackageManager.getInstalledApplication()
вызов возвращает список всех установленных приложений. Добавление определенных флагов позволяет получить много дополнительных данных. Это может привести к сбою, поэтому рекомендуется не извлекать дополнительные данные и извлекать их отдельно для каждого приложения.Однако вызов все равно может быть неудачным, поэтому важно
catch
заключить его в точку и при необходимости повторить попытку.Насколько я знаю, для решения этой проблемы нет обходного пути, кроме повторных попыток и получения как можно меньшего количества информации.
источник
Я тоже получил это исключение на Samsung S3. Я подозреваю 2 основных причины,
Используйте DDMS и просматривайте свою кучу во время игры в своем приложении, что даст вам некоторое представление о том, какой setcontentview создает проблему.
Я скопировал все Drawables во всех папках, чтобы избавиться от проблемы 2.
Проблема решена.
источник
Добавьте это в свою активность
Это работает для меня, надеюсь, это также поможет вам
источник
onCreate()
?Поэтому для нас это была попытка отправить слишком большой объект через наш интерфейс AIDL в удаленный сервис. Размер транзакции не может превышать 1 МБ. Запрос разбивается на отдельные блоки по 512 КБ и отправляется по одному через интерфейс. Брутальное решение, которое я знаю, но эй - его Android :(
источник
Вы очистили свой старый InstanceState из метода onSaveInstanceState , и он будет работать хорошо. Я использую FragmentStatePagerAdapter для моего viewpager, поэтому я оставляю ниже метод Override в моей родительской активности для очистки InstanceState.
Я нашел это решение отсюда android.os.TransactionTooLargeException на Nougat
источник
Недавно я также столкнулся с интересным случаем при работе с поставщиком контактов Android .
Мне нужно было загрузить фотографии контактов из внутренней базы данных контактов, и в соответствии с архитектурой системы все эти данные доставляются по запросам поставщику контактов.
Поскольку он работает как отдельное приложение - все виды передачи данных выполняются с использованием механизма Binder, поэтому здесь вступает в действие буфер Binder.
Моя главная ошибка заключалась в том , что я не закрывался
Cursor
с данными BLOb получил от контактов поставщика, так что память , выделенная для поставщика увеличилась , и это раздувается Переплетчик буфер , пока я не получил тонны!!!FAILED BINDER TRANSACTION!!!
сообщений в моем выходе LogCat.Поэтому основная идея заключается в том, что когда вы работаете с внешними контент-провайдерами и получаете
Cursor
от них информацию, всегда закрывайте его, когда заканчиваете работать с ними.источник
Я столкнулся с той же проблемой, когда пытался отправить растровое изображение через Intent, и в то же время, когда это происходит, я складывал приложение.
Как это описано в этой статье, введите описание ссылки, здесь это происходит, когда активность находится в процессе остановки, это означает, что активность пыталась отправить свои сохраненные пакеты состояния в ОС системы для безопасного хранения для восстановления позже (после изменения конфигурации или обработать смерть), но один или несколько Пакетов были слишком большими.
Я решил это с помощью хака, переопределив onSaveInstanceState в моей деятельности:
и комментируйте, звоните супер. Это грязный хак, но он работает отлично. Растр был успешно отправлен без сбоев. Надеюсь, это кому-нибудь поможет.
источник
В моем случае я получаю TransactionTooLargeException в качестве вторичного сбоя после сбоя собственной библиотеки с SIGSEGV. Собственный сбой библиотеки не сообщается, поэтому я получаю только TransactionTooLargeException.
источник
Я получил это в моем syncadapter, когда пытаюсь навалом вставить большое ContentValues []. Я решил исправить это следующим образом:
источник
Для меня это было также
FragmentStatePagerAdapter
, однако переопределениеsaveState()
не работало. Вот как я это исправил:При вызове
FragmentStatePagerAdapter
конструктора сохраните отдельный список фрагментов в классе и добавьте метод для удаления фрагментов:Затем в
Activity
, сохранитеViewPager
позицию и вызовитеadapter.removeFragments()
переопределенныйonSaveInstanceState()
метод:Наконец, в переопределенном
onResume()
методе повторно создайте экземпляр адаптера, если это не такnull
. (Если это такnull
, тоActivity
он открывается в первый раз или после того, как приложение было уничтожено Android, в которомonCreate
будет выполняться создание адаптера.)источник
Убедитесь, что вы не вводите в объект объекта «Данные» большого размера. В моем случае я добавил размер строки 500k, а затем начал другое действие. Это всегда терпело неудачу с этим исключением. Я избегал обмена данными между действиями, используя статические переменные действий - вам не нужно отправлять их в Intent, а затем извлекать из них.
Что у меня было:
источник
Когда я имею дело с
WebView
в моем приложении, это происходит. Я думаю, что это связано сaddView
ресурсами UI. В моем приложении я добавляю немного кода,WebViewActivity
как показано ниже, тогда он работает нормально:источник
Я нашел основную причину этого (мы получили как «ошибка добавления окна», так и утечку файлового дескриптора, как говорит mvds).
Существует ошибка в
BitmapFactory.decodeFileDescriptor()
Андроиде 4.4. Это происходит только тогда, когдаinPurgeable
иinInputShareable
дляBitmapOptions
установленыtrue
. Это вызывает много проблем во многих местах взаимодействия с файлами.Обратите внимание, что метод также вызывается из
MediaStore.Images.Thumbnails.getThumbnail()
.Universal Image Loader подвержен этой проблеме. Пикассо и Глайд, похоже, не пострадали. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020
источник
Эта одна строка кода в методе writeToParcel (Parcel dest, int flags) помогла мне избавиться от TransactionTooLargeException.
Только после этого кода я записываю все данные в объект посылки, т.е. dest.writeInt () и т. Д.
источник
Попробуйте использовать
EventBus
илиContentProvider
как решение.Если вы находитесь в одном и том же процессе (как правило, все ваши действия будут), попробуйте использовать
EventBus
, потому что в процессе обмена данными НЕ требуется какой-то буфер, поэтому вам не нужно беспокоиться о том, что ваши данные слишком велики. (Вы можете просто использовать вызов метода, чтобы действительно передать данные, а EventBus скрыть ужасные вещи) Вот деталь:Если две стороны намерения не находятся в одном и том же процессе, попробуйте несколько
ContentProvider
.Смотрите TransactionTooLargeException
источник
Я получил TransactionTooLargeException из-за ошибки Stackoverflow в тесте Android Espresso. Я обнаружил трассировку стека ошибок переполнения стека в журналах, когда снял фильтр Logcat для своего приложения.
Я предполагаю, что Espresso вызвал TransactionTooLargeException при попытке обработать действительно большую трассировку стека исключений.
источник
Можно использовать:
в манифесте Android под тегом приложения.
Это решило проблему в моем случае!
источник
onSaveInstantState
действий / фрагментов и сохранения больших списков) это не помогло.Кроме того, я столкнулся с этой проблемой для передачи растровых данных от одного действия к другому, но я делаю решение, превращая свои данные в статические данные, и это работает идеально для меня
В деятельности сначала:
и во втором упражнении:
источник
Это происходило в моем приложении, потому что я передавал список результатов поиска в аргументах фрагмента, назначая этот список свойству фрагмента - которое фактически является ссылкой на то же место в памяти, на которое указывают аргументы фрагмента, - затем добавляя новые элементы в списке, которые также изменили размер аргументов фрагмента. Когда действие приостанавливается, базовый класс фрагмента пытается сохранить аргументы фрагмента в onSaveInstanceState, который вылетает, если аргументы больше 1 МБ. Например:
Самым простым решением в этом случае было присвоение копии списка свойству фрагмента вместо назначения ссылки:
Еще лучшим решением было бы не передавать столько данных в аргументах.
Я, вероятно, никогда бы не нашел это без помощи этого ответа и TooLargeTool .
источник
Я также жил TransactionTooLargeException. Во-первых, я работал, чтобы понять, где это происходит. Я знаю причину, почему это происходит. Каждый из нас знает из-за большого содержания. Моя проблема была такой, и я решил. Может быть, это решение может быть полезным для всех. У меня есть приложение, которое получает контент от API. Я получаю результат от API на первом экране и отправляю его на второй экран. Я могу отправить этот контент на второй экран в случае успеха. После второго экрана, если я хочу перейти на третий экран, возникает это исключение. Каждый мой экран создан из фрагмента. Я заметил, что когда ухожу со второго экрана. Сохраняет содержимое пакета. если этот контент слишком велик, это исключение происходит. Мое решение - после того, как я получил контент из пакета, я очищаю его.
источник
Решением может быть приложение для записи ArrayList (или любого объекта, вызывающего проблему) в файловую систему, затем передача ссылки на этот файл (например, имя файла / путь) через Intent в IntentService и затем возможность IntentService. получить содержимое файла и преобразовать его обратно в ArrayList.
Когда IntentService завершил работу с файлом, он должен либо удалить его, либо передать инструкцию обратно через приложение Local Broadcast, чтобы удалить созданный файл (возвращая ту же ссылку на файл, которая была ему предоставлена).
Для получения дополнительной информации см. Мой ответ на эту проблему .
источник
В качестве Intents, контент-провайдеры, Messenger, все системные службы, такие как телефон, вибратор и т. Д., Используют провайдера инфраструктуры IPC от Binder. Более того, обратные вызовы жизненного цикла активности также используют эту инфраструктуру.
1 МБ - это общий лимит для всех транзакций связывания, выполняемых в системе в определенный момент.
Если при отправке намерения происходит много транзакций, он может завершиться неудачей, даже если дополнительные данные невелики. http://codetheory.in/an-overview-of-android-binder-framework/
источник
В очень многих местах, где может произойти TransactionTooLargeException - вот еще одно новшество в Android 8 - сбой, когда кто-то просто начинает печатать в EditText, если содержимое слишком велико.
Это связано с AutoFillManager (новым в API 26) и следующим кодом в
StartSessionLocked()
:Если я правильно понимаю, это вызывает службу автозаполнения - передавая AutofillManagerClient в связывателе. И когда EditText имеет много контента, он, похоже, вызывает TTLE.
Несколько вещей могут смягчить это (или сделали так, как я тестировал в любом случае): Добавьте
android:importantForAutofill="noExcludeDescendants"
в объявление макета EditText xml. Или в коде:2 - ая ужасный, ужасный обходной путь может быть также переопределить
performClick()
иonWindowFocusChanged()
методы , чтобы поймать ошибку в самом TextEdit подкласса. Но я не думаю, что это действительно мудро ...источник