Recently, the image data will be transferred from the service side to the client side. The previous data is transferred through Aidl:
Create a Parcelable file
ImageData.java
public class ImageData implements Parcelable {
private byte[] data;
public byte[] getData() {
return data;
}
public ImageData(byte[] dataIn) {
this.data = dataIn;
}
public ImageData(Parcel in) {
int arrayLength = in.readInt();
if (arrayLength > 0) {
data = new byte[arrayLength];
in.readByteArray(data);
}
}
@Override
public void writeToParcel(Parcel dest, int flags) {
if (data != null && data.length > 0) {
dest.writeInt(data.length);
dest.writeByteArray(data);
} else {
dest.writeInt(0);
}
}
...
}
test.aidl
interface test {
void sendMessage(ImageData data);
}
Operation error:
android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:514)
…
reason
The main reason for deadobjectexception here is that the buffer created by the binder is full:
kernel/msm-4.4/drivers/android/binder_alloc.c
315 if (best_fit == NULL) {
…
341 pr_err(“%d: binder_alloc_buf size %zd failed, no address space\n”,
342 alloc->pid, size);
343 pr_err(“allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n”,
344 total_alloc_size, allocated_buffers, largest_alloc_size,
345 total_free_size, free_buffers, largest_free_size);
346 eret = ERR_PTR(-ENOSPC);
347 goto error_unlock;
348 }
If the data in transmission is greater than free_ Buffers, a deadobjectexception will be thrown
solve
1.socket
Socke transmission is not limited by size, but its implementation is complex
2. Documents
File transfer is relatively simple, but inefficient, and the higher version will be limited by the permissions of the Android system
3. Data cutting
Cutting large data into smaller data transmission is a scheme with good efficiency and complexity
Define data body:
public class SliceData implements Parcelable {
private byte[] data;
private int length;
...
}
Cutting data method:
public static byte[][] divideArray(byte[] source, int chunkSize) {
int totalLength = source.length;
int arraySize = (int) Math.ceil(totalLength / (double) chunkSize);
byte[][] ret = new byte[arraySize][chunkSize];
int start = 0;
int parts = 0;
for (int i = 0; i < arraySize; i++) {
if (start + chunkSize > totalLength) {
System.arraycopy(source, start, ret[i], 0, source.length - start);
} else {
System.arraycopy(source, start, ret[i], 0, chunkSize);
}
start += chunkSize;
parts++;
}
return ret;
}
Build and send slicedata in order:
byte[][] divideData = divideArray(testBytes, 64 * 1024);//64k
for (byte[] item : divideData) {
mEmitter.onNext(new SliceData(length, item));
}
Client reception:
int chunkSize = bytes.length;
if(buffer == null) {
buffer = new byte[length];
index = 0;
}
If (index + chunksize > bodylength) {// last data block
System.arraycopy(bytes, 0, buffer, index, bodyLength - index);
visualResultData.bitmap = BitmapFactory.decodeByteArray(buffer, 0, buffer.length);
buffer = null;
index = 0;
} else {
System.arraycopy(bytes, 0, buffer, index, chunkSize);
index += chunkSize;
}
4. Third party
The binder itself also uses MMAP. You can use the framework that implements MMAP, such as mmkv
5.Bitmap
If the transmitted data is bitmap, the putbinder scheme of bundle can also be used
Define binder:
class ImageBinder extends IRemoteGetBitmap.Stub {
@Override
public Bitmap getBitMap() throws RemoteException {
return mBitmap;
}
}
send out
Bundle bundle = new Bundle();
bundle.putBinder("bitmap", new ImageBinder());
intent.putExtras(bundle);
receive:
ImageBinder imageBinder = (ImageBinder) bundle.getBinder("bitmap");
Bitmap bitmap = imageBinder.getBitmap();
This is the end of this article on the implementation of Android cross process big data transmission. For more information about Android cross process big data transmission, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!