aidl传输文件有大小1M限制,单次传输不适合传递大数据,可以使用aidl传递共享内存引用ParcelFileDescriptor方式传递图片信息。具体实现如下
一、service端
1.1.aidl文件IIpcService.aidl 定义,这里主要用到pfd参数
interface IIpcService {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
// void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
// double aDouble, String aString);
void register2Server(String packageName,IIpcServiceListener ipcServiceListener);
void unregister2Server(String packageName);
String processClientRequest(String packageName,String clientRequest,inout ParcelFileDescriptor pfd);
}
1.2 service端 处理客户端传递的图片 流 引用ParcelFileDescriptor ,将获取的ParcelFileDescriptor转换成Bitmap 并回调给ui层显示
public String processClientRequest(String packageName, String clientRequest, ParcelFileDescriptor pfd) {
Log.i(TAG, "processClientRequest 11 packageName:" + packageName
+ " clientRequest:" + clientRequest + " pfd:" + pfd);
String ret = clientRequest;
FileDescriptor fileDescriptor = pfd.getFileDescriptor();
FileInputStream fis = null;
try {
fis = new FileInputStream(fileDescriptor);
Bitmap rawBitmap = BitmapFactory.decodeStream(fis);
ret += " process success!";
Log.i(TAG, "processClientRequest 222 rawBitmap ByteCount:" + rawBitmap.getByteCount() + " mUiShow:" + mUiShow);
if (null != mUiShow) {
mUiShow.showBitmap(rawBitmap);
}
} catch (Exception e) {
Log.i(TAG, "processClientRequest 22 error:" + e);
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
Log.i(TAG, "processClientRequest 33 error:" + e);
}
}
Log.i(TAG, "processClientRequest 22 end ret:" + ret);
return ret;
}
1.3 也可以处理客户端传递的字节数组 数据引用,处理代码如下
public String processClientRequest(String packageName, String clientRequest, ParcelFileDescriptor pfd) {
Log.i(TAG, "processClientRequest 11 packageName:" + packageName
+ " clientRequest:" + clientRequest + " pfd:" + pfd);
String ret = clientRequest;
FileDescriptor fileDescriptor = pfd.getFileDescriptor();
FileInputStream fis = null;
try {
fis = new FileInputStream(fileDescriptor);
byte [] content = new byte[5];
fis.read(content);
Log.i(TAG, "processClientRequest 111 content:" + content);
for(int i=0;i<content.length;i++){
Log.i(TAG, "processClientRequest 113 content["+i+"]=" + content[i]);
}
}
} catch (Exception e) {
Log.i(TAG, "processClientRequest 33 error:" + e);
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
Log.i(TAG, "processClientRequest 44 error:" + e);
}
}
Log.i(TAG, "processClientRequest 55 end ret:" + ret);
return ret;
}
二客户端
2.1 客户端连接到service后,调用接口 传递图片文件引用 ParcelFileDescriptor
String path = "/sdcard/lilei/20230207161749238.jpg";
public ParcelFileDescriptor getPfd() {
ParcelFileDescriptor pfd = null;
try {
pfd = ParcelFileDescriptor.open(new File(path), MODE_READ_WRITE);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "getPfd() pfd:" + pfd);
return pfd;
}
public String sendFile(String requestJson) {
Log.i(TAG, "sendFile() requestJson:" + requestJson);
if (null != mFtIpcManager) {
return mFtIpcManager.processClientRequest(requestJson, getPfd());
}
return "error";
}
2.2 客户端也可以传递 byte数组
public ParcelFileDescriptor getTextPfd() {
ParcelFileDescriptor pfd = null;
try {
MemoryFile memoryFile = new MemoryFile("test", 1024);
Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
FileDescriptor des = (FileDescriptor) method.invoke(memoryFile);
pfd = ParcelFileDescriptor.dup(des);
//向内存中写入字节数组
memoryFile.getOutputStream().write(new byte[]{1,2,5,4,3});
//关闭流
memoryFile.getOutputStream().close();
memoryFile.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);a
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "getTextPfd() pfd:" + pfd);
return pfd;
}
public String sendFile(String requestJson) {
Log.i(TAG, "sendFile() requestJson:" + requestJson);
if (null != mFtIpcManager) {
return mFtIpcManager.processClientRequest(requestJson, getTextPfd());
}
return "error";
}
2.3 客户端也可以传递Bitmap数据,需要先将Bitmap转换成 byte数组,service端接收同1.2
public ParcelFileDescriptor getBitmapPfd() {
ParcelFileDescriptor pfd = null;
Bitmap bitmap= BitmapFactory.decodeResource(FtClientApp.getAppContext().getResources(), R.drawable.btn_send);
//将Bitmap转成字节数组
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
try {
MemoryFile memoryFile = new MemoryFile("test", bitmap.getByteCount());
Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor");
FileDescriptor des = (FileDescriptor) method.invoke(memoryFile);
pfd = ParcelFileDescriptor.dup(des);
//向内存中写入字节数组
memoryFile.getOutputStream().write(byteArray);
//关闭流
memoryFile.getOutputStream().close();
memoryFile.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "getPfd() pfd:" + pfd);
return pfd;
}
public String sendFile(String requestJson) {
Log.i(TAG, "sendFile() requestJson:" + requestJson);
if (null != mFtIpcManager) {
return mFtIpcManager.processClientRequest(requestJson, getBitmapPfd());
}
return "error";
}
PS:这里也可以共享内存传递大字符串,只是需要将字符串和字节数组转换一下再传递,转换实现如下。
1.string 字符串转换成 byte[] 数组
String str = "reagan";
byte[] srtbyte = str.getBytes();
2.byte[] 数组转换成 string字符串
String res = new String(srtbyte);
或者
String res = new String(srtbyte,"UTF-8");
System.out.println(res);
----------
如下服务端1.2 log 所示,服务端可以接受客户端2.3发送 的 31M左右的图片数据
2024-01-09 01:14:45.797 11247-11267 SimpleTestActivity com.android.demo.lileidemo I showBitmap() bitmap:android.graphics.Bitmap@3fe9243 getByteCount:33177600
2024-01-09 01:14:45.798 11247-11267 lileiDemo_...sitoryImpl com.android.demo.lileidemo I processClientRequest 55 end ret:image process success!