parent
23291525ce
commit
de364e2bf7
@ -0,0 +1,89 @@ |
||||
--- |
||||
跨进程传递大图片 |
||||
--- |
||||
|
||||
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 机制 |
Loading…
Reference in new issue