TransactionTooLargeException异常

 

一、问题以及解决方案

TransactionTooLargeException异常是一个很不常见的异常,开发几年了,首次遇到这个异常,一部分手机会出现这种情况,当时还很惊奇。最后经查找原来是Activity启动时候intent数据传递过大发生的。当时是一个分享功能的偶发bug,在分享时候传递数据包括标题、链接,网址,截图等参数,截图传递的是截取的Bitmap,果然是Bitmap太大了,导致部分机型TransactionTooLargeException:

    System.err: java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 2056292 bytes
                at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3998)

经过代码追踪,发现intent在putBundle之前把Bitmap添加到Bundle里面,这才是根源,最后把Bitmap经过质量压缩为原来的百分之30才不崩溃了:

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    resource.compress(Bitmap.CompressFormat.JPEG, 30, bos);
    byte[] bytes = bos.toByteArray();
    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

二、异常原因

从上面的问题上可以看出通过intent在页面间传递数据是有大小限制的,但通常我们平时传递少量数据的时候是没问题的。在Activity之前传递数据的时候从intent中携带的数据是需要从APP进程传输到AMS进程,再由AMS进程传输到目标Activity所在进程。但是目标的Activity不一定是APP所在的进行,有可能是其他进程。因为Activity的startActivity方法是原生支持跨进程通信的,例如我们通过隐式意图启动其他APP的Activity或者目标Activity在Manifest.xml配置了process属性,这时候当前Activity和目标Activity就不再同一个进程。这也不难理解startActivity传递数据的数据层不是在APP层面处理的,而是在binder中进行数据传递。普通的由Zygote孵化而来的用户进程,所映射的Binder内存大小是不到1M的,如果传输说句超过这个大小,系统就会报错,因为Binder本身就是为了进程间频繁而灵活的通信所设计的,并不是为了拷贝大数据而使用的,TransactionTooLargeException源码注释也可以看出:

 * The Binder transaction buffer has a limited fixed size, currently 1Mb, which
 * is shared by all transactions in progress for the process.  Consequently this
 * exception can be thrown when there are many transactions in progress even when
 * most of the individual transactions are of moderate size.

 

你可能感兴趣的:(android)