Android跨進(jìn)程傳遞大數(shù)據(jù)的方法實現(xiàn)
最近要從Service端給Client端傳遞圖片數(shù)據(jù),之前的數(shù)據(jù)都是通過aidl傳遞:
創(chuàng)建 Parcelable文件
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);
}
運行報錯:
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)
...
原因
這里導(dǎo)致DeadObjectException的原因主要是binder創(chuàng)建的buffer被占滿了:
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 }
傳輸中如果數(shù)據(jù)大于free_buffers,則會拋出DeadObjectException
解決
1.socket
socke傳輸不受大小限制,但實現(xiàn)比較復(fù)雜
2.文件
通過文件傳輸比較簡單,但效率差,而且高版本會受到Android系統(tǒng)權(quán)限限制
3.數(shù)據(jù)切割
將較大數(shù)據(jù)切割成較小的數(shù)據(jù)傳輸,此方法是兼顧效率,復(fù)雜度較好的方案
定義數(shù)據(jù)體:
public class SliceData implements Parcelable {
private byte[] data;
private int length;
...
}
切割數(shù)據(jù)方法:
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;
}
將SliceData按順序構(gòu)建發(fā)送:
byte[][] divideData = divideArray(testBytes, 64 * 1024);//64k
for (byte[] item : divideData) {
mEmitter.onNext(new SliceData(length, item));
}
client接收:
int chunkSize = bytes.length;
if(buffer == null) {
buffer = new byte[length];
index = 0;
}
if (index + chunkSize > bodyLength) {//最后一個數(shù)據(jù)塊
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.第三方
binder本身也是利用mmap,可以利用實現(xiàn)mmap的框架,比如 MMKV
5.Bitmap
如果傳輸?shù)臄?shù)據(jù)是Bitmap,還可以用Bundle的putBinder方案
定義binder:
class ImageBinder extends IRemoteGetBitmap.Stub {
@Override
public Bitmap getBitMap() throws RemoteException {
return mBitmap;
}
}
發(fā)送
Bundle bundle = new Bundle();
bundle.putBinder("bitmap", new ImageBinder());
intent.putExtras(bundle);
接收:
ImageBinder imageBinder = (ImageBinder) bundle.getBinder("bitmap");
Bitmap bitmap = imageBinder.getBitmap();
到此這篇關(guān)于Android跨進(jìn)程傳遞大數(shù)據(jù)的方法實現(xiàn)的文章就介紹到這了,更多相關(guān)Android跨進(jìn)程傳遞大數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android數(shù)據(jù)類型之間相互轉(zhuǎn)換系統(tǒng)介紹
一些初學(xué)Android的朋友可能會遇到JAVA的數(shù)據(jù)類型之間轉(zhuǎn)換的苦惱;本文將為有這類需求的朋友解決此類問題2012-11-11
Android Studio輕松構(gòu)建自定義模板的步驟記錄
這篇文章主要給大家介紹了關(guān)于Android Studio輕松構(gòu)建自定義模板的相關(guān)資料,文中通過示例代碼以及圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10
Android實現(xiàn)底部帶刻度的進(jìn)度條樣式
由于公司需要一個帶刻度的進(jìn)度條樣式,因為刻度需要動態(tài)去改變,所以換背景圖片的方案肯定是不行的,唯一的辦法就是自己繪制一個進(jìn)度條,下面小編給大家?guī)砹薃ndroid實現(xiàn)底部帶刻度的進(jìn)度條樣式及實例代碼,需要的朋友參考下吧2019-10-10

