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