You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.5 KiB

---
跨进程传递大图片
---
1. 了解各种跨进程传输数据的方式及各自优缺点
2. 了解 TransactionTooLargeException 的触发原因和底层机制
3. 了解 Bitmap 传输底层原理
#### 方案
1. 给图片保存到固定的地方,传 key 给对方
2. 通过 IPC 的方式转发图片数据
1. Binder
2. Socket、管道
3. 共享内存
#### TransactionTooLargeException
1. 发出去的或者返回的数据量太大
2. Binder 缓存用于该进程所有正在进行中的 Binder 事务
3. 大数据量打碎分批发,或按需发
```c++
jboolean BinderProxy_transact(JNIEnv* env, ...){
status_t err = target->transact(code, *data, reply, flags);
signalExceptionForError(env, obj, err, true, data->dataSize());
return JNI_FALSE;
}
void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, ...){
switch(err){
case FAILED_TRANSACTION:{
if(canThrowRemoteException && parcelSize > 200*1024){
exceptionToThrow = "android/os/TransactionTooLargeException";
}
jniThrowException(env, exceptionToThrow, msg);
}break;
}
}
```
```c++
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
while(1){
if((err=talkWithDriver())<NO_ERROR)break;
switch(cmd){
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
}
}
return err;
}
void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply){
t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags&TF_ONE_WAY));
if(t>buffer == NULL){
return_error = BR_FAILED_REPLY;
goto err_binder_alloc_buf_failed;
}
}
```
```java
Bundle b = new Bundle();
b.putParcelable("bitmap", mBitmap);
intent.putExtra(b);
Bundle b = new Bundle();
b.putBinder("binder", new IRemoteCaller.Stub(){
@Override
public Bitmap getBitmap() throws RemoteException{
return mBitmap;
}
});
intent.putExtras(b);
```
```java
int startActivity(IApplicationThread caller, String callingPackage, Intent intent, ...){
Parcel data = Parcel.obtain();
intent.writeToParcel(data, 0);
mRemote.transct(START_ACTIVITY_TRANSACTION, data, reply, 0);
}
```
#### 总结:怎么跨进程传递大图片?
1. 图片写到文件,路径传到另一个进程,再读出来
2. intent 传图,但是容易抛异常,原因是什么?
3. binder 调用传图,底层 ashmem 机制