TransactionTooLargeException when opening pick image intent (Kotlin, Android)

Viewed 461

I'm currently working on my app, and I have a fragment where the user can pick an image to insert into a database. This works, but when I go on my edit fragment and try to use the same code again to pick an image, I get an TransactionTooLargeException.

Error

2020-12-26 23:23:45.919 3837-3837/com.google.gradient.red E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.google.gradient.red, PID: 3837
    java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 7007624 bytes
        at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)
        at android.os.Handler.handleCallback(Handler.java:888)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:213)
        at android.app.ActivityThread.main(ActivityThread.java:8178)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
     Caused by: android.os.TransactionTooLargeException: data parcel size 7007624 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(BinderProxy.java:526)
        at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4561)
        at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
        at android.os.Handler.handleCallback(Handler.java:888) 
        at android.os.Handler.dispatchMessage(Handler.java:100) 
        at android.os.Looper.loop(Looper.java:213) 
        at android.app.ActivityThread.main(ActivityThread.java:8178) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101) 

What I've tried

I saw some solutions saying to put something like this into my code that triggers with the image intent, but I still get the same error. I might be doing something wrong, but I'm not sure.

override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.clear()
    }

Code

Here is my OnCreateView where I set the setOnClickListener:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_update, container, false)

        // Set menu
        setHasOptionsMenu(true)

        // Get bitmap
        bitmap = args.currentItem.image

        view.current_title_et.setText(args.currentItem.title)
        view.current_description_et.setText(args.currentItem.description)
        view.current_mood_spinner.setSelection(mSharedViewModel.parseMood(args.currentItem.mood))
        view.current_mood_spinner.onItemSelectedListener = mSharedViewModel.listener

        // Opens gallery when image button clicked, gets image
        view.current_image_et.setOnClickListener {
            readStorageTask()
            //Intent to pick image
            val intent = Intent(Intent.ACTION_PICK)
            intent.type = "image/*"
            startActivityForResult(intent, 1001)
        }

        return view
    }

I'm trying to make it so that users can edit images in my app and don't know how I would solve this bug, so any help would be greatly appreciated!

2 Answers

I ran into the same issue as I was switching my code to use ViewModel. It was working fine before, not sure if that had an impact but here's how I fixed it.

doing outState.clear() fixed the crash, but of course is not ideal as it clears all the outState for me also made it so I couldn't process the images.

So I used outState.keySet() in loop and printed each key. Then put outState.remove(key) for each key, and commented out each key 1 at a time until I found the one that caused the crash. For me it was "android:support:fragments".

I'm assuming this is because I was launching the gallery from the fragment, and also calling onActivityResult() from the fragment. So the only thing I needed to remove from the outState was outState.remove("android:support:fragments"), this just meant I needed to launch the gallery intent from the activity, and process it from there too.

It's still not an ideal fix as I'm sure I'm causing more problems by removing the fragments outstate, but it's a good temporary fix for now, I will update when I have time to research more into it, or maybe someone who is more familiar with the lifecycle in ViewModels that can find a better solution.

TL;DR:

add outState.remove("android:support:fragments") to your activity's onSavedInstanceState() and launch gallery and process onActivityResult() from the activity.

Using an Intent is not the way how to do it, because of the limitation of 1024kb per Bundle.
See https://developer.android.com/guide/components/activities/parcelables-and-bundles

You could either a) save the image to file-system and only pass back the file-name (to be preferred) or b) add a customApplication class (which is always present) and then exchange the data by setting a static field in there, from where it then can be obtained again.

Related