Search code examples
androidandroid-intentandroid-bitmap

TransactionTooLargeException on API 28+ when sharing bitmap despite using Intent.EXTRA_STREAM


I am trying to share a bitmap via an intent to all apps that can handle images.Despite having follwed the instructions in several stack overflow answers like this one and on android developers my code produces as TransactionTooLargeException on API 28+ and some devices below. Eventhough i am always using Intent.EXTRA_STREAM and never send the bitmap direclty.

  1. My first, simple approach:
         val intent = Intent(Intent.ACTION_SEND).apply {
                type = "image/jpeg"
                putExtra(Intent.EXTRA_STREAM, getImageUri(context!!, bitmap))
            }
            startActivity(Intent.createChooser(intent, "Share image"))



     fun getImageUri(inContext: Context, inImage: Bitmap): Uri {
    val bytes = ByteArrayOutputStream()
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes)
    val path = MediaStore.Images.Media.insertImage(inContext.contentResolver, inImage, "Title", null)
    return Uri.parse(path) }
  1. I also tried retrieving the uri via provider:

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"
            tools:replace="android:resource" />
    </provider>
    

provider_paths.xml:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="external_files" path="."/>
<cache-path name="external_files" path="."/>
<cache-path name="shared_images" path="images/"/>
<external-path name="external_files" path="."/>
<external-files-path name="external_files" path="."/>
<external-cache-path name="external_files" path="."/>

Retrieve the uri, continue like in 1.:

  val uri = FileProvider.getUriForFile(it.activity, "...", file)

Stacktrace originating from my 1. approach:

    2019-06-02 17:10:51.255 19592-19592/... E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 9344028)
2019-06-02 17:10:51.292 19592-19592/... E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ..., PID: 19592
    java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 9344028 bytes
        at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3998)
        at android.os.Handler.handleCallback(Handler.java:794)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:6635)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
     Caused by: android.os.TransactionTooLargeException: data parcel size 9344028 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(Binder.java:774)
        at android.app.IActivityManager$Stub$Proxy.activityStopped(IActivityManager.java:4723)
        at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3982)
        at android.os.Handler.handleCallback(Handler.java:794) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:176) 
        at android.app.ActivityThread.main(ActivityThread.java:6635) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823) 

PS: I have added <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> to my manifest


Solution

  • As it turns out you just have to add this to your activity. It clears the Activity's bundle of the subsidiary fragments' bundles.

     override fun onSaveInstanceState(outState: Bundle) {
            super.onSaveInstanceState(outState)
            //FIX: TransactionTooLargeException when sharing image via intent. Clear the Activity's bundle of the subsidiary fragments' bundles.
            outState.clear()
        }