Android.Os.Transactiontoolargeexception on Nougat

android.os.TransactionTooLargeException on Nougat

In the end, my problem was with things that were being saved onSaveInstance, and not with things that were being sent to the next activity. I removed all saves where I can't control the size of objects (network responses), and now it's working.

Update 2:

Google now provides AndroidX ViewModel which is based on the same technology as retained Fragments but much easier to use. Now ViewModel is a preferred approach.

Update 1:

To preserve big chunks of data, Google is suggesting to do it with Fragment that retains instance. Idea is to create an empty Fragment without a view with all necessary fields, that would otherwise be saved in the Bundle. Add setRetainInstance(true); to Fragment's onCreate method.
And then save data in Fragment on Activity's onDestroy and load them onCreate.
Here is an example of Activity:

public class MyActivity extends Activity {

private DataFragment dataFragment;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

// create the fragment and data the first time
if (dataFragment == null) {
// add the fragment
dataFragment = new DataFragment();
fm.beginTransaction().add(dataFragment, “data”).commit();
// load the data from the web
dataFragment.setData(loadMyData());
}

// the data is available in dataFragment.getData()
...
}

@Override
public void onDestroy() {
super.onDestroy();
// store the data in the fragment
dataFragment.setData(collectMyLoadedData());
}
}

An example of Fragment:

public class DataFragment extends Fragment {

// data object we want to retain
private MyDataObject data;

// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}

public void setData(MyDataObject data) {
this.data = data;
}

public MyDataObject getData() {
return data;
}
}

More about it, you can read here.

TransactionTooLargeException in Nougat

Your are passing too much data to your Fragment in setArguments(). Your Fragment will work, but when it tries to save its instance state it overflows the transaction buffer. This throws a RuntimeException if you target Android 7.0 (API 24 or higher). To preserve backwards compatibility and not break existing apps, the new behaviour is only used if you target API 24 or higher. If you target API < 24, the transaction buffer overflow exception is caught and silently ignored. This means that your data will not be persistently saved, which you may (or may not) notice.

Your code is broken. You should not pass large amounts of data to the Fragment in setArguments(). You can keep your data in your Activity. When the Fragment wants to access the data, it can always so something like this:

// Get the owning Activity
MyActivity activity = (MyActivity)getActivity();
// Get the data from the Activity
List<Data> data = activity.getData();

In your Activity, write a getData() method that returns a reference to whatever data the Fragment needs.

In this way, the data is held in the Activity and the Fragment can get access to it whenever it needs to.

TransactionTooLargeException only on Nougat

I have the same problem. This has been complained by many developers on the google forum. Their answer is WAI (work as intended) because they don't recommend to save too much data in the state.
So the advice is to only add very basic arguments to an Intent.
If you want to send data among activities or fragments,

  • Store the data in a (temporary) file and pass around the file URI.
    This option is probably your only option if you want to transfer
    large amounts of data to a completely different app. Store the data
    in the Application instance;
  • Create a singleton container holding the
    data you pass around.
  • If you are using FragmentStatePageAdapter, add the following code to avoid it saving state data.

    @Override    
    public Parcelable saveState() {
    Bundle bundle = (Bundle) super.saveState();
    bundle.putParcelableArray("states", null); // Never maintain any states from the base class to avoid TransactionTooLargeException
    return bundle;
    }

Reference:

https://issuetracker.google.com/issues/37103380

https://www.neotechsoftware.com/blog/android-intent-size-limit

android.os.TransactionTooLargeException: data parcel size NOUGAT ERROR

This is the typical error when you put a large amount of data into Bundle of Android.

I would suggest you do it right. The large data has to persistent to disk (either database or files) and you only pass the reference of this data to other places to consume it.

Here you may find 30kb is small, but the actual configuration of size limit for Bundle may be various from different devices/vendors configurations.

The Bundle was meant to keep simple and small data only, don't over-abuse it.

TransactionTooLargeException nougat only

This happens when you try to put more than 1mb of data in an Intent.

If your onCreate is doing anything like inserting initial data, you should consider doing it in several smaller batches (applyBatch) to avoid the issue. if you're trying to do something with images or other large data, your only options may be to reduce their size, or only pass a handle which allows you to access the file later

What to do on TransactionTooLargeException

I encountered this issue, and I found that when there huge amount of data getting exchanged between a service and an application,(This involves transferring lots of thumbnails). Actually data size was around 500kb, and the IPC transaction buffer size is set to 1024KB. I am not sure why it exceeded the transaction buffer.

This also can occur, when you pass lot of data through intent extras

When you get this exception in your application, please analyze your code.

  1. Are you exchanging lot of data between your services and application?
  2. Using intents to share huge data, (for example, the user selects huge number of files from gallery share press share, the URIs of the selected files will be transferred using intents)
  3. receiving bitmap files from service
  4. waiting for android to respond back with huge data (for example, getInstalledApplications() when the user installed lot of applications)
  5. using applyBatch() with lot of operations pending

How to handle when you get this exception

If possible, split the big operation in to small chunks, for example, instead of calling applyBatch() with 1000 operations, call it with 100 each.

Do not exchange huge data (>1MB) between services and application

I dont know how to do this, but, Do not query android, which can return huge data :-)

How do I figure out what is causing android.os.TransactionTooLargeException

Yup! As of Android 7.0 (Nougat) the system will crash if the data in onSaveInstanceState is too large.

You'll have to figure out another way to save and restore state.

http://blog.sqisland.com/2016/09/transactiontoolargeexception-crashes-nougat.html

Note this comment from Dianne Hackborn:

Dianne Hackborn September 18, 2016 at 10:52 AM

It is more complicated than a fixed size limit. Each process has a
fixed buffer for receiving incoming transactions, whose size is 1MB.
So technically you could say the maximum size is 1MB, but that assumes
there are no other IPCs happening. In practice, you should never have
a size anywhere close to that, or you run the risk of occasionally
failing when there are a number of other concurrent IPCs in progress.

For the specific case of saved state, you also want to keep this small
because whatever you provide here is data the system needs to hold on
to in the system process for as long as the user can ever navigate
back to that activity (even if the activity's process is killed).

So I would recommend keeping the saved state well less than 100K, and
really less than 50K, and in most cases much less than even that.



Related Topics



Leave a reply



Submit