Что делать с TransactionTooLargeException

Я получил 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

Ответ 1

Я столкнулся с этой проблемой, и я обнаружил, что когда между сервисом и приложением происходит обмен огромным количеством данных (это связано с переносом большого количества миниатюр). Фактически размер данных составлял около 500 кбайт, а размер буфера транзакций IPC установлен равным 1024 КБ. Я не уверен, почему он превысил буфер транзакции.

Это также может произойти, когда вы передаете много данных с помощью дополнительных настроек

Когда вы получите это исключение в своем приложении, проанализируйте свой код.

  • Вы обмениваете много данных между вашими услугами и приложением?
  • Используя намерения обмениваться огромными данными (например, пользователь выбирает огромное количество файлов из общей папки общего доступа к общей папке, URI выбранных файлов будут переданы с использованием намерений)
  • получение растровых файлов из службы
  • ожидание андроида для ответа огромными данными (например, getInstalledApplications(), когда пользователь установил много приложений)
  • с помощью applyBatch() с большим количеством ожидающих операций

Как обращаться с этим исключением

Если возможно, разделите большую операцию на маленькие куски, например, вместо вызова applyBatch() с 1000 операций, вызовите его по 100.

Не обменивайте огромные данные ( > 1 МБ) между службами и приложением

Я не знаю, как это сделать, но не запрашивайте андроид, который может возвращать огромные данные: -)

Ответ 2

Это не окончательный ответ, но он может пролить свет на причины TransactionTooLargeException и помочь определить проблему.

Хотя большинство ответов относятся к большому количеству переданных данных, я вижу, что это исключение выбрасывается случайно после интенсивной прокрутки и масштабирования и многократно открывает меню счетчика ActionBar. Авария происходит при нажатии панели действий. (это настраиваемое приложение для сопоставления)

Единственные передаваемые данные кажутся касаниями от "Input Dispatcher" к приложению. Я думаю, что это не может разумно равняться примерно 1 мб в "Буфере транзакций".

Мое приложение работает на четырехъядерном процессоре с тактовой частотой 1,6 ГГц и использует 3 потока для тяжелой атлетики, сохраняя один ядро ​​свободным для потока пользовательского интерфейса. Кроме того, приложение использует андроид: largeHeap, имеет 10 мб неиспользуемой кучи слева и имеет 100 мб комнаты, чтобы увеличить кучу. Поэтому я бы не сказал, что это проблема с ресурсами.

Сбой всегда всегда предшествует следующим строкам:

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 !!!

которые не обязательно печатаются в этом порядке, но (насколько я проверял) происходят на той же миллисекунде.

И сама трассировка стека, для ясности, такая же, как в вопросе:

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

Вводя исходный код android, вы обнаружите следующие строки:

рамки/база/ядро ​​/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);

Мне кажется, что я, возможно, ударил эту недокументированную функцию, когда транзакция завершилась неудачно по другим причинам, чем транзакция TooLarge. Они должны были назвать его TransactionTooLargeOrAnotherReasonException.

В это время я не решил проблему, но если я найду что-то полезное, я обновлю этот ответ.

update: выяснилось, что мой код просочился в некоторые файловые дескрипторы, число которых максимизировано в linux (обычно 1024), и это, похоже, вызвало исключение. Так что это была проблема с ресурсами. Я проверил это, открыв /dev/zero 1024 раза, что привело к появлению всех видов странных исключений в действиях, связанных с пользовательским интерфейсом, включая исключение выше и даже некоторые SIGSEGV. Очевидно, что отказ от открытия файла/сокета не является тем, что обрабатывается/сообщается очень чисто на Android.

Ответ 3

Если вам нужно исследовать, какая посылка вызывает ваш крах, вам следует попробовать попробовать TooLargeTool.

(Я нашел это как комментарий от @Max Spencer в соответствии с принятым ответом, и это было полезно в моем случае.)

Ответ 4

TransactionTooLargeException преследует нас примерно 4 месяца, и мы, наконец, решили проблему!

Что происходит, мы использовали FragmentStatePagerAdapter в ViewPager. Пользователь будет просматривать страницы и создавать более 100 фрагментов (приложение для чтения).

Хотя мы правильно управляем фрагментами в destroyItem(), в андроидах при реализации FragmentStatePagerAdapter появляется ошибка, в которой она содержит ссылку на следующий список:

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

И когда Android FragmentStatePagerAdapter пытается сохранить состояние, он вызывается функцией

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

Как вы можете видеть, даже если вы правильно управляете фрагментами в подклассе FragmentStatePagerAdapter, базовый класс все равно сохранит Fragment.SavedState для каждого отдельного фрагмента, когда-либо созданного. TransactionTooLargeException возникнет, когда этот массив будет сброшен в parcelableArray, и OS не понравится более 100 элементов.

Поэтому исправление для нас должно было переопределить метод saveState() и не хранить что-либо для "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;
}

Ответ 5

Для тех, кто сильно разочарован в поисках ответа о том, почему появляется TransactionTooLargeException, попытайтесь проверить, сколько информации вы сохранили в состоянии экземпляра.

При компиляции /targetSdkVersion & lt; = 23 у нас есть только внутреннее предупреждение о большом размере сохраненного состояния, но ничего не происходит:

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)

Но при компиляции /targetSdkVersion> = 24 мы имеем реальный сбой RuntimeException в этом случае:

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) 

Что делать?

Сохраняйте данные в локальной базе данных и сохраняйте только идентификатор в состоянии экземпляра, который вы можете использовать для извлечения этих данных.

Ответ 6

Не существует одной конкретной причины этой проблемы. Для меня в моем классе Fragment я делал это:

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;
}

вместо этого:

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

Ответ 7

Это исключение обычно выдается при отправке приложения в фоновом режиме.

Поэтому я решил использовать метод фрагментирования данных, чтобы полностью обойти жизненный цикл onSavedInstanceStae. Мое решение также обрабатывает сложные состояния экземпляров и освобождает память как можно скорее.

Сначала я создал простой Fargment для хранения данных:

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;
    }
}

Затем в своей основной Деятельности я полностью обхожу цикл сохраненных экземпляров и переношу ответственность за мой фрагмент данных. Нет необходимости использовать это на самих фрагментах, так как их состояние автоматически добавляется в состояние "Активность":

@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
}

Осталось просто вставить сохраненный экземпляр:

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

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

Полная информация: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/

Ответ 8

У меня тоже есть это исключение на Samsung S3. Я подозреваю 2 причины,

  1. у вас есть растровые изображения, которые загружают и занимают слишком много памяти, используют сокращение
  2. У вас есть некоторые недостатки в папках drawable-_dpi, android ищет их в drawable и изменяет их размеры, заставляя ваш setContentView внезапно прыгать и использовать много памяти.

Используйте DDMS и смотрите на свою кучу, когда играете в свое приложение, и это даст вам некоторые указания, по которым setcontentview создает проблему.

Я скопировал все чертежи во всех папках, чтобы избавиться от проблемы 2.

Проблема разрешена.

Ответ 9

Важно понимать, что буфер транзакций ограничен 1 МБ, независимо от возможностей устройства или приложения. Этот буфер используется с каждым вызовом API, который вы делаете, и делится между всеми транзакциями, в которых выполняется приложение.

Я считаю, что он также содержит некоторые конкретные объекты, такие как посылки и такие (Parcel.obtain()), поэтому важно всегда сопоставлять каждый obtain() с recycle().

Эта ошибка может быть легко вызвана вызовами API, возвращающими много данных, даже если возвращаемые данные меньше 1 МБ (если другие транзакции все еще запущены).

Например, вызов PackageManager.getInstalledApplication() возвращает список всех установленных приложений. Добавление определенных флагов позволяет получить много дополнительных данных. Это может привести к сбою, поэтому рекомендуется не извлекать лишние данные и извлекать их для каждого приложения.

Однако вызов может по-прежнему терпеть неудачу, поэтому важно окружить его с помощью catch и при необходимости повторить попытку.

Насколько я знаю, нет никакой проблемы с такой проблемой, кроме повторной попытки и получения как можно меньше информации.

Ответ 10

Добавьте это в свою деятельность

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

Это работает для меня, надеюсь, это поможет вам

Ответ 11

Итак, для нас это было то, что мы пытались отправить слишком большой объект через наш интерфейс AIDL в удаленную службу. Размер транзакции не может превышать 1 МБ. Запрос разбивается на отдельные куски 512 Кбайт и отправляется по одному через интерфейс. Жестокое решение, которое я знаю, но эй - его Android: (

Ответ 12

Недавно я также столкнулся с интересным случаем во время работы с Android Поставщик контактов.

Мне нужно было загружать фотографии контактов из базы данных внутренних контактов, и в соответствии с архитектурой системы все эти данные доставляются по запросам поставщику контактов.

Поскольку он работает как отдельное приложение - все виды передачи данных выполняются с использованием механизма Binder, и поэтому здесь включается буфер Binder.

Моя основная ошибка заключалась в том, что я не закрыл Cursor с данными blob, полученными из поставщика контактов, так что память, выделенная для провайдера, увеличилась, и это надуло буфер Binder до тех пор, пока я не получил тонны сообщений !!!FAILED BINDER TRANSACTION!!! в моем выходе LogCat.

Итак, основная идея заключается в том, что когда вы работаете с внешними поставщиками контента и получаете от них Cursor, всегда закрывайте его, когда вы завершаете работу с ними.

Ответ 13

В моем случае я получаю TransactionTooLargeException как вторичный сбой после того, как родная библиотека разбилась с SIGSEGV. Сбой родной библиотеки не сообщается, поэтому я получаю TransactionTooLargeException.

Ответ 14

Я получил это в своем syncadapter при попытке bulkInsert большой ContentValues ​​[]. Я решил исправить это следующим образом:

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));
}

Ответ 15

Для меня это был также FragmentStatePagerAdapter, однако переопределение saveState() не saveState(). Вот как я его исправил:

При вызове конструктора FragmentStatePagerAdapter сохраните отдельный список фрагментов внутри класса и добавьте метод удаления фрагментов:

class PagerAdapter extends FragmentStatePagerAdapter {
    ArrayList<Fragment> items;

    PagerAdapter(ArrayList<Fragment> frags) {
        super(getFragmentManager()); //or getChildFragmentManager() or getSupportFragmentManager()
        this.items = new ArrayList<>();
        this.items.addAll(frags);
    }

    public void removeFragments() {
        Iterator<Fragment> iter = items.iterator();

        while (iter.hasNext()) {
            Fragment item = iter.next();
                getFragmentManager().beginTransaction().remove(item).commit();
                iter.remove();
            }
            notifyDataSetChanged();
        }
    }
    //...getItem() and etc methods...
}

Затем в Activity, сохранить ViewPager положение и вызвать adapter.removeFragments() в перегруженной onSaveInstanceState() метод:

private int pagerPosition;

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

Наконец, в переопределенном onResume() повторно onResume() экземпляр адаптера, если он не равен null. (Если он равен null, Activity открывается в первый раз или после того, как приложение было убито Android, в котором onCreate будет создавать адаптер.)

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

Ответ 16

Убедитесь, что вы не помещаете данные объекта Intent большого размера. В моем случае я добавлял размер String 500k, а затем запускал другое действие. Это исключение всегда не срабатывало. Я избегал обмена данными между действиями с помощью статических переменных действий - вам не нужно отправлять их в Intent, а затем извлекать из него.

Что у меня было:

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);

Ответ 17

Когда я занимаюсь с WebView в моем приложении, это происходит. Я думаю, что это связано с ресурсами addView и UI. В моем приложении я добавляю код в WebViewActivity, как показано ниже, и он работает нормально:

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

Ответ 18

Я нашел основную причину этого (мы получили как "сбой добавления окна", так и утечку дескриптора файла, как говорит mvds).

В BitmapFactory.decodeFileDescriptor() Android 4.4 есть ошибка . Это происходит только тогда, когда inPurgeable и inInputShareable of BitmapOptions установлены на true. Это приводит к тому, что многие проблемы во многих местах взаимодействуют с файлами.

Обратите внимание, что метод также вызывается из MediaStore.Images.Thumbnails.getThumbnail().

Универсальный загрузчик изображений затронут этой проблемой. Пикассо и Глейд, похоже, не затронуты. https://github.com/nostra13/Android-Universal-Image-Loader/issues/1020

Ответ 19

Эта одна строка кода в методе writeToParcel (Parcel dest, int flags) помогла мне избавиться от TransactionTooLargeException.

dest=Parcel.obtain(); 

После этого кода только я пишу все данные в объект посылки, т.е. Dest.writeInt() и т.д.

Ответ 20

Попробуйте использовать EventBus или ContentProvider как раствор.

Если вы находитесь в одном и том же процессе (как правило, все ваши действия будут), попробуйте использовать EventBus, потому что при обмене данными процесса НЕ нужен несколько буфер, поэтому вам не нужно беспокоиться о том, что ваши данные слишком велики. (Вы можете просто использовать вызов метода для передачи данных действительно, а EventBus скрыть уродливые вещи) Вот деталь:

// one side
startActivity(intentNotTooLarge);
EventBus.getDefault().post(new FooEvent(theHugeData));

// the other side
@Subscribe public void handleData(FooEvent event) { /* get and handle data */ }

Если обе стороны намерения не находятся в одном процессе, попробуйте несколько ContentProvider.


См. TransactionTooLargeException

Сбой транзакции Binder, потому что он слишком велик.

Во время удаленного вызова процедуры аргументы и возвращаемое значение вызова передаются как объекты Parcel, хранящиеся в буфере транзакции Binder. Если аргументы или возвращаемое значение слишком велики для размещения в буфере транзакций, тогда вызов завершится с ошибкой и будет выведено TransactionTooLargeException.

Ответ 21

Я столкнулся с той же проблемой, когда пытался отправить растровое изображение через Intent, и в то же время, когда это произошло, я сбросил приложение.

Как описано в этой статье, введите описание ссылки здесь, когда это происходит, когда Activity находится в процессе остановки, это означает, что Activity пыталась отправить сохраненные состояния Bundles в системную ОС для безопасного сохранения для восстановления позже (после изменения конфигурации или процесс смерти), но что один или несколько связок, которые он отправил, были слишком большими.

Я решил это с помощью взлома, переопределив onSaveInstanceState в моей деятельности:

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

и комментарий супер. Это грязный хак, но он отлично работает. Растровое изображение было успешно отправлено без сбоев. Надеюсь, это поможет кому-то.

Ответ 22

Я получил TransactionTooLargeException из ошибки Stackoverflow в тесте Android Espresso. Я обнаружил трассировку стека ошибок stackoverflow в журналах, когда я снял фильтр Logcat для своего приложения.

Я предполагаю, что Espresso вызвал TransactionTooLargeException при попытке обработать действительно большое исключение stacktrace.

Ответ 23

Вы очистите свой старый экземпляр InstanceState методом onSaveInstanceState, и он будет работать хорошо. Я использую FragmentStatePagerAdapter для моего viewpager, поэтому я держу ниже метод Override в моей родительской активности для очистки экземпляра InstanceState.

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

Я нашел это решение здесь android.os.TransactionTooLargeException в Nougat

Ответ 24

Можно использовать:

android:largeHeap="true"

в Android Manifest под тегом приложения.

Это решило проблему в моем случае!

Ответ 25

Кроме того, я столкнулся с этой проблемой для данных Bitmap, передаваемых от одного действия к другому, но я делаю решение, сделав свои данные статическими данными, и это отлично работает для меня

В первую очередь:

public static Bitmap bitmap_image;

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

и во второй деятельности:

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

Ответ 26

Это происходило в моем приложении, потому что я передавал список результатов поиска в аргументах фрагмента, назначая этот список свойству фрагмента - которое фактически является ссылкой на то же место в памяти, на которое указывают аргументы фрагмента, - затем добавляя новые элементы в списке, которые также изменили размер фрагмента аргументов. Когда действие приостанавливается, базовый класс фрагмента пытается сохранить аргументы фрагмента в onSaveInstanceState, который вылетает, если аргументы превышают 1 МБ. Например:

private ArrayList<SearchResult> mSearchResults;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if (getArguments() != null && getArguments().getSerializable("SearchResults") != null) {
        mSearchResults = (ArrayList) getArguments().getSerializable("SearchResults");
    }
}

private void onSearchResultsObtained(ArrayList<SearchResult> pSearchResults) {

    // Because mSearchResults points to the same location in memory as the fragment arguments
    // this will also increase the size of the arguments!
    mSearchResults.addAll(pSearchResults);
}

Самым простым решением в этом случае было присвоение копии списка свойству фрагмента вместо назначения ссылки:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if (getArguments() != null && getArguments().getSerializable("SearchResults") != null) {

        // Copy value of array instead of reference
        mSearchResults = new ArrayList((ArrayList) getArguments().getSerializable("SearchResults"));
    }
}

Еще лучшим решением было бы не передавать столько данных в аргументах.

Я, вероятно, никогда бы не нашел это без помощи этого ответа и TooLargeTool.

Ответ 27

Решением было бы приложение написать ArrayList (или любой объект, вызывающий проблему) в файловую систему, затем передать ссылку на этот файл (например, имя файла/путь) через Intent на IntentService, а затем пусть IntentService извлекает содержимое файла и преобразует его обратно в ArrayList.

Когда IntentService сделал с файлом, он должен либо удалить его, либо передать инструкцию обратно в приложение через локальную широковещательную рассылку, чтобы удалить созданный файл (передав туда ту же ссылку на файл, которая была ему предоставлена).

Для получения дополнительной информации см. мой ответ на эту связанную проблему.

Ответ 28

В качестве намерений, поставщиков контента, Messenger, все системные службы, такие как Telephone, Vibrator и т.д. используют провайдера инфраструктуры IPC по Binder.Moreover обратные вызовы жизненного цикла активности также используют эту инфраструктуру.

1MB - это общий предел для всех транзакций связующего, выполненных в системе в определенный момент.

В случае, если при отправке намерения происходит много транзакций, может произойти сбой, даже если дополнительные данные невелики. http://codetheory.in/an-overview-of-android-binder-framework/

Ответ 29

С таким количеством мест, где TransactionTooLargeException может happen-- здесь появиться еще одно новое для Android 8 - сбой, когда кто-то просто начинает вводить текст EditText, если содержимое слишком велико.

Это связано с AutoFillManager (новый в API 26) и следующий код в StartSessionLocked():

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

Если я правильно понимаю, это вызывает автозаполнение service--, передающее AutofillManagerClient внутри связующего. И когда EditText имеет много контента, он, кажется, вызывает TTLE.

Несколько вещей могут смягчить его (или, как я уже тестировал): Добавить android:importantForAutofill="noExcludeDescendants" в объявлении макета XML-объявления EditText. Или в коде:

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);
}

performClick() ужасным, ужасным обходным performClick() также может быть переопределить performClick() и onWindowFocusChanged() чтобы поймать ошибку в подклассе TextEdit. Но я не думаю, что мудрый действительно...

Ответ 30

Для меня TransactionTooLargeException произошло, когда я попытался отправить большое растровое изображение из одной активности в другую с помощью намерения. Я решил эту проблему, используя глобальные переменные приложения.

Например, если вы хотите отправить большое изображение растрового изображения из действия A в активность B, сохраните это растровое изображение в глобальной переменной

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

затем запустите операцию B и прочитайте из глобальной переменной

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