JavaBinder: !!! FAILED BINDER TRANSACTION !!! 异常的解决方案分析
出现的缘由
本人一直负责公司车机端多媒体app软件的开发工作,最近负责的一个项目的情形是:在A Activity读取外接U盘中的图片文件,封装:
public class MediaFileBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name = "";
private String time = "";
private String path = "";
private Bitmap bitmap;//图片第一帧,即缩略图
private String fileName = "";
private int isLove = -1;
private FileFormat fileFormate;
private String sortLetters;
......
}
并以列表显示缩略图,当点击显示图片时,再把所有的数据传递给B(专门用于显示图片):
AActivity.java:
private void enterBActivity(ArrayList<MediaFileBean> mPhotoList, int position) {
Intent intent = new Intent(mActivity, BActivity.class);
intent.putExtra(Constants.PHOTO_ITEM_LIST, mPhotoList);//将扫描出来的图片文件传递给B
intent.putExtra(Constants.PHOTO_CURRENT_POSITION, position);
startActivity(intent);
}
B中接收A发来的数据:
//onCreate()中调用initData()
public void initData() {
......
mPhotoList = (ArrayList<MediaFileBean>) getIntent().getSerializableExtra(Constants.PHOTO_ITEM_LIST);
currentPosition = getIntent().getIntExtra(Constants.PHOTO_CURRENT_POSITION, -1);
......
}
可是如果U盘中含有大量的图片时,无论怎么点,就是进不去B页面,程序也不crash,后台打印logcat,发现出现 JavaBinder: !!! FAILED BINDER TRANSACTION !!! 错误
出现的原因
网上搜索了一遍,大致的原因就是用Intent传递数据时,Bitmap不能大于40KB,而根据官网的介绍,Intent传递数据有限制,最大为1M左右
解决的办法
1.尽可能的不再Intent中传递Bitmap。可以先把要传递的bitmap保存在SD中,Intent中传递时用url地址代替。
2.如果实在要对Bitmap进行传递,可以先对其压缩
`/**
* 压缩图片
* 该方法引用自:http://blog.csdn.net/demonliuhui/article/details/52949203
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
return bitmap;
}`
3.将要传递的数据改成全局变量
如果要传递的量大,上述的方法2也是于事无补的。比如说我的上述问题,即使在bean中去掉bitmap变量,还是会报错,因为我要传递的数组实在太大了!换一种思路,将要传递的数据放在一个固定的生命周期中的值里,随时赋值随时取值,想到这,放在Application中很合适:
public class MediaApplication extends Application {
// 用于传递的图片数据
private List<MediaFileBean> mPhotoList;
private static MediaApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public synchronized static MediaApplication getInstance() {
return mInstance;
}
public void setPhotoList(ArrayList<MediaFileBean> list){
this.mPhotoList = list;
}
public List<MediaFileBean> getPhotoList(){
return this.mPhotoList;
}
}
A向B跳转时改为:
private void enterBActivity(ArrayList<MediaFileBean> mPhotoList, int position) {
MediaApplication.getInstance().setPhotoList(mPhotoList);
Intent intent = new Intent(mActivity, BActivity.class);
intent.putExtra(Constants.PHOTO_CURRENT_POSITION, position);
startActivity(intent);
}
B中接收A的数据:
@Override
public void initData() {
mPhotoList = (ArrayList<MediaFileBean>) MediaApplication.getInstance().getPhotoList();// 解决异常:JavaBinder: !!! FAILED BINDER TRANSACTION !!!
currentPosition = getIntent().getIntExtra(Constants.PHOTO_CURRENT_POSITION, -1);
}