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.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值