Android跨进程通信传输大数据
16lz
2021-12-04
Android跨进程通信的方式大概有如下几种:
1.Activity方式:
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" ); startActivity(callIntent);
2.Content Provider 方式:
Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据),应用程序可以利用Content Provider完成下面的工作1. 查询数据2. 修改数据3. 添加数据4. 删除数据
3.广播方式:
Intent intent = new Intent(“com.android.ACTION_TEST”);intent.putExtra("value","content");mContext.sendBroadcast(intent);
4.LocalSocket方式
客户端LocalSocket代码//创建对象LocalSocket localSocket = new LocalSocket();//连接socketServerSocketlocalSocket.connect(new LocalSocketAddress(String addrStr));获取localSocket的输入输出流:outputStream = localSocket.getOutputStream();inputStream = localSocket.getInputStream();写入数据:outputStream.write("数据".getBytes());循环接收数据:try { int readed = inputStream.read(); int size = 0; byte[] bytes = new byte[0]; while (readed != -1) { byte[] copy = new byte[500000]; System.arraycopy(bytes, 0, copy, 0, bytes.length); bytes = copy; bytes[size++] = (byte) readed; //以换行符标识成结束 if ('\n' == (byte) readed) { String resultStr = new String(bytes, 0, size); break; } readed = inputStream.read(); }} catch (IOException e) { return false;}服务端LocalServerSocket代码//初始化try { //socketAddress需跟localSocket地址一致,否则无法连接上 serverSocket = new LocalServerSocket(socketAddress);} catch (IOException e) { LoggerHelper.e("Server to establish connection exception:" + e.toString()); e.printStackTrace(); return false;}try { //获取接收的LocalSocket localSocket = serverSocket.accept(); //设置缓冲大小 localSocket.setReceiveBufferSize(ConstantConfig.BUFFER_SIZE); localSocket.setSendBufferSize(ConstantConfig.BUFFER_SIZE);} catch (IOException e) { e.printStackTrace(); LoggerHelper.d("Waiting to be linked to a bug,error:" + e.toString()); return false;}获取输入输出流一致:if (localSocket != null) { try { inputStream = localSocket.getInputStream(); outputStream = localSocket.getOutputStream(); /** 允许一直接收数据,一直到连接被断开,则认为应用端退出,自己也退出 */ while (isLock && receiveData()) ; } catch (IOException e) { LoggerHelper.e("Get stream exception:" + e.toString()); e.printStackTrace(); return false; }}
5.AIDL Service方式
这也是本文采取的主要方式,通过AIDL读取共享内存的方式去实现大数据的传输
5.1首先定义两个AIDL文件,注意服务端和客户端的两个文件要一样,并且放在同一个文件夹下。
服务端使用package com.example.administrator.testgsensor;import com.example.administrator.testgsensor.ITestCallbackAidlInterface;// Declare any non-default types here with import statementsinterface ITestAidlInterface { void registerCallback(ITestCallbackAidlInterface cb); void unregisterCallback(ITestCallbackAidlInterface cb); ParcelFileDescriptor getMemoryFileDescriptor(); void serverSendData(String data);}
客户端使用// ITestCallbackAidlInterface.aidlpackage com.example.administrator.testgsensor;// Declare any non-default types here with import statementsinterface ITestCallbackAidlInterface { void clintSenddata(String data);}
服务端实现代码package com.example.administrator.testgsensor;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.MemoryFile;import android.os.ParcelFileDescriptor;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.util.Log;import java.io.FileDescriptor;import java.io.IOException;import java.lang.reflect.Method;public class TestService extends Service{ private String TAG = "TestService"; private TestInterface mTestInterface = new TestInterface(); final RemoteCallbackList<ITestCallbackAidlInterface> mCallbackList = new RemoteCallbackList<ITestCallbackAidlInterface>(); private MemoryFile mMemoryFile = null; private ParcelFileDescriptor pfd = null; private boolean isRunFlag = false; private FileDescriptor fd; @Override public void onCreate(){ super.onCreate(); } @Override public void onDestroy(){ super.onDestroy(); } @Override public IBinder onBind(Intent intent) { isRunFlag = true; return mTestInterface; } @Override public void onStart(Intent intent, int startId){ super.onStart(intent, startId); } @Override public boolean onUnbind(Intent intent){ isRunFlag = false; if (mMemoryFile != null){ mMemoryFile.close(); mMemoryFile = null; } return super.onUnbind(intent); }//实现接口ITestAidlInterface public class TestInterface extends ITestAidlInterface.Stub { @Override public void registerCallback(ITestCallbackAidlInterface cb) throws RemoteException { if(cb != null) mCallbackList.register(cb); } @Override public void unregisterCallback(ITestCallbackAidlInterface cb) throws RemoteException { if(cb != null) mCallbackList.unregister(cb); } @Override public ParcelFileDescriptor getMemoryFileDescriptor() throws RemoteException { if (pfd == null){ createMemoryFile(); } if (pfd != null && !pfd.getFileDescriptor().valid()){ if (mMemoryFile != null){ mMemoryFile.close(); mMemoryFile = null; } try { pfd.close(); pfd = null; } catch (IOException e) { e.printStackTrace(); } createMemoryFile(); } return pfd; } @Override public void serverSendData(String data) throws RemoteException { //客户端返回数据 } }//创建共享内存块 private void createMemoryFile(){ if (mMemoryFile == null){ try { mMemoryFile = new MemoryFile("memfile", 1000); Method method = MemoryFile.class.getDeclaredMethod("getFileDescriptor"); fd = (FileDescriptor) method.invoke(mMemoryFile); if (fd.valid()){ Log.d(TAG, "createMemoryFile: fd valid"); pfd = ParcelFileDescriptor.dup(fd); new Thread(testRunnable ).start(); }else { Log.e(TAG, "createMemoryFile: fd = -1"); } } catch (Exception e) { e.printStackTrace(); if (mMemoryFile != null){ mMemoryFile.close(); mMemoryFile = null; } pfd = null; } } } Runnable testRunnable = new Runnable() { @Override public void run() { try { while (isRunFlag){ byte[] testData = {0x01,0x02,0x03}; if (fd.valid()) { //往内存块里面写数据 mMemoryFile.writeBytes(testData, 0, 0, testData.length); } else { writeStop(); } Thread.sleep(10); } isRunFlag = false; } catch (Exception e) { e.printStackTrace(); } finally { isRunFlag = false; } } };//发送数据给客户端 private void writeStop() { final int n = mCallbackList.beginBroadcast(); for (int i=0; i < n; i++) { try { mCallbackList.getBroadcastItem(i).clintSenddata("stop"); } catch (RemoteException e) { e.printStackTrace(); } } mCallbackList.finishBroadcast(); }}记得在AndroidManifest.xml中注册service<service android:name="com.example.administrator.testgsensor.TestService" android:enabled="true" android:exported="true"> <intent-filter > <action android:name="com.example.administrator.testgsensor.TestService" /> </intent-filter></service>
接下来看客户端的代码
客户端代码package com.example.administrator.testgsensor;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.MemoryFile;import android.os.ParcelFileDescriptor;import android.os.RemoteException;import android.util.Log;import java.io.IOException;public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private boolean isBind = false; private ITestAidlInterface mTestAidlInterface; private MemoryFile mMemoryFile; private boolean bRead = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); binderService(); bRead = true; new Thread(new Runnable() { @Override public void run() { byte[] data = new byte[3]; while (bRead){ if (mTestAidlInterface != null && mMemoryFile != null) { try { //读取共享内存块的数据 mMemoryFile.readBytes(data, 0, 0, data.length); } catch (IOException e) { e.printStackTrace(); } } } } }).start(); } @Override protected void onDestroy() { if (mTestAidlInterface != null) { try { mTestAidlInterface.unregisterCallback(testCallbackAidlInterface); } catch (RemoteException e) { e.printStackTrace(); } } unBinderService(); super.onDestroy(); } private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { if (mTestAidlInterface == null) { mTestAidlInterface = ITestAidlInterface.Stub.asInterface(service); Log.d(TAG, "onServiceConnected: "); if (mTestAidlInterface != null) { try { mTestAidlInterface.registerCallback(testCallbackAidlInterface); //获取共享内存文件描述符 ParcelFileDescriptor pfd = mTestAidlInterface.getMemoryFileDescriptor(); if (pfd != null) { Log.d(TAG, "pfd != null "+pfd.toString()); mMemoryFile = MemoryFileHelper.openMemoryFile(pfd, 1000, MemoryFileHelper.PROT_READ); } } catch (RemoteException e) { e.printStackTrace(); } } } } @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "onServiceDisconnected: ");//正常情况下是不会被调用的,只有远程服务意外停止才会 unBinderService(); } }; ITestCallbackAidlInterface testCallbackAidlInterface = new ITestCallbackAidlInterface.Stub() { @Override public void clintSenddata(String data) throws RemoteException { //服务端发送数据 } }; private void binderService() { Intent intent = new Intent(); intent.setAction("com.example.administrator.testgsensor.TestService"); intent.setPackage("com.example.administrator.testgsensor"); intent.setClassName("com.example.administrator.testgsensor", "com.example.administrator.testgsensor.TestService"); this.bindService(intent, conn, Context.BIND_AUTO_CREATE); isBind = true; } private void unBinderService() { if (isBind) { this.unbindService(conn); isBind = false; }else { return; } testCallbackAidlInterface = null; if (mMemoryFile != null) { mMemoryFile.close(); mMemoryFile = null; } }}
到此服务端和客户端的代码已经完成,两个进程间就可以通过读写共享内存块的方式共享大数据啦。
最后附上两个工具类的代码。
package com.example.administrator.testgsensor;import android.os.MemoryFile;import android.os.ParcelFileDescriptor;import android.util.Log;import java.io.FileDescriptor;import java.io.IOException;import java.lang.reflect.Method;public class MemoryFileHelper { public static final int PROT_READ = 0x01;//只读方式打开, public static final int PROT_WRITE = 0x02;//可写方式打开,PROT_WRITE|PROT_READ可读可写方式打开 private static final String TAG = "MemoryFileHelper"; /** * 创建共享内存对象 * * @param name 描述共享内存文件名称 * @param length 用于指定创建多大的共享内存对象 * @return MemoryFile 描述共享内存对象 */ public static MemoryFile createMemoryFile(String name, int length) { try { return new MemoryFile(name, length); } catch (IOException e) { e.printStackTrace(); } return null; } public static MemoryFile openMemoryFile(ParcelFileDescriptor pfd, int length, int mode) { if (pfd == null) { throw new IllegalArgumentException("ParcelFileDescriptor 不能为空"); } FileDescriptor fd = pfd.getFileDescriptor(); Log.d(TAG, "openMemoryFile: pfd="+pfd.toString()); Log.d(TAG, "openMemoryFile: fd="+fd.toString()); return openMemoryFile(fd, length, mode); } /** * 打开共享内存,一般是一个地方创建了一块共享内存 * 另一个地方持有描述这块共享内存的文件描述符,调用 * 此方法即可获得一个描述那块共享内存的MemoryFile * 对象 * * @param fd 文件描述 * @param length 共享内存的大小 * @param mode PROT_READ = 0x1只读方式打开, * PROT_WRITE = 0x2可写方式打开, * PROT_WRITE|PROT_READ可读可写方式打开 * @return MemoryFile */ public static MemoryFile openMemoryFile(FileDescriptor fd, int length, int mode) { MemoryFile memoryFile = null; try { memoryFile = new MemoryFile("tem", length); memoryFile.close(); Class<?> c = MemoryFile.class; Method native_mmap = null; Method[] ms = c.getDeclaredMethods(); for (int i = 0; ms != null && i < ms.length; i++) { if (ms[i].getName().equals("native_mmap")) { native_mmap = ms[i]; } } ReflectUtil.setField("android.os.MemoryFile", memoryFile, "mFD", fd); ReflectUtil.setField("android.os.MemoryFile", memoryFile, "mLength", length); //address 在4.4中是int类型,在6.0中是long类型。 long address = (Integer) ReflectUtil.invokeMethod(null, native_mmap, fd, length, mode); ReflectUtil.setField("android.os.MemoryFile", memoryFile, "mAddress", address); Log.d(TAG, "openMemoryFile: mFD"+fd.toString()); Log.d(TAG, "openMemoryFile: mLength"+length); Log.d(TAG, "openMemoryFile: mAddress"+address); } catch (Exception e) { e.printStackTrace(); } return memoryFile; } /** * 获取memoryFile的ParcelFileDescriptor * * @param memoryFile 描述一块共享内存 * @return ParcelFileDescriptor */ public static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile memoryFile) { if (memoryFile == null) { throw new IllegalArgumentException("memoryFile 不能为空"); } ParcelFileDescriptor pfd; FileDescriptor fd = getFileDescriptor(memoryFile); pfd = (ParcelFileDescriptor) ReflectUtil.getInstance("android.os.ParcelFileDescriptor", fd); return pfd; } /** * 获取memoryFile的FileDescriptor * * @param memoryFile 描述一块共享内存 * @return 这块共享内存对应的文件描述符 */ public static FileDescriptor getFileDescriptor(MemoryFile memoryFile) { if (memoryFile == null) { throw new IllegalArgumentException("memoryFile 不能为空"); } FileDescriptor fd; fd = (FileDescriptor) ReflectUtil.invoke("android.os.MemoryFile", memoryFile, "getFileDescriptor"); return fd; }}
package com.example.administrator.testgsensor;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class ReflectUtil { /** * 根据类名,参数实例化对象 * * @param className 类的路径全名 * @param params 构造函数需要的参数 * @return 返回T类型的一个对象 */ public static Object getInstance(String className, Object... params) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className 不能为空"); } try { Class<?> c = Class.forName(className); if (params != null) { int plength = params.length; Class[] paramsTypes = new Class[plength]; for (int i = 0; i < plength; i++) { paramsTypes[i] = params[i].getClass(); } Constructor constructor = c.getDeclaredConstructor(paramsTypes); constructor.setAccessible(true); return constructor.newInstance(params); } Constructor constructor = c.getDeclaredConstructor(); constructor.setAccessible(true); return constructor.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 执行instance的方法 * * @param className 类的全名 * @param instance 对应的对象,为null时执行类的静态方法 * @param methodName 方法名称 * @param params 参数 */ public static Object invoke(String className, Object instance, String methodName, Object... params) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className 不能为空"); } if (methodName == null || methodName.equals("")) { throw new IllegalArgumentException("methodName不能为空"); } try { Class<?> c = Class.forName(className); if (params != null) { int plength = params.length; Class[] paramsTypes = new Class[plength]; for (int i = 0; i < plength; i++) { paramsTypes[i] = params[i].getClass(); } Method method = c.getDeclaredMethod(methodName, paramsTypes); method.setAccessible(true); return method.invoke(instance, params); } Method method = c.getDeclaredMethod(methodName); method.setAccessible(true); return method.invoke(instance); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 执行指定的对方法 * * @param instance 需要执行该方法的对象,为空时,执行静态方法 * @param m 需要执行的方法对象 * @param params 方法对应的参数 * @return 方法m执行的返回值 */ public static Object invokeMethod(Object instance, Method m, Object... params) { if (m == null) { throw new IllegalArgumentException("method 不能为空"); } m.setAccessible(true); try { return m.invoke(instance, params); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 取得属性值 * * @param className 类的全名 * @param fieldName 属性名 * @param instance 对应的对象,为null时取静态变量 * @return 属性对应的值 */ public static Object getField(String className, Object instance, String fieldName) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className 不能为空"); } if (fieldName == null || fieldName.equals("")) { throw new IllegalArgumentException("fieldName 不能为空"); } try { Class c = Class.forName(className); Field field = c.getDeclaredField(fieldName); field.setAccessible(true); return field.get(instance); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 设置属性 * * @param className 类的全名 * @param fieldName 属性名 * @param instance 对应的对象,为null时改变的是静态变量 * @param value 值 */ public static void setField(String className, Object instance, String fieldName, Object value) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className 不能为空"); } if (fieldName == null || fieldName.equals("")) { throw new IllegalArgumentException("fieldName 不能为空"); } try { Class<?> c = Class.forName(className); Field field = c.getDeclaredField(fieldName); field.setAccessible(true); field.set(instance, value); } catch (Exception e) { e.printStackTrace(); } } /** * 根据方法名,类名,参数获取方法 * * @param className 类名,全名称 * @param methodName 方法名 * @param paramsType 参数类型列表 * @return 方法对象 */ public static Method getMethod(String className, String methodName, Class... paramsType) { if (className == null || className.equals("")) { throw new IllegalArgumentException("className 不能为空"); } if (methodName == null || methodName.equals("")) { throw new IllegalArgumentException("methodName不能为空"); } try { Class<?> c = Class.forName(className); return c.getDeclaredMethod(methodName, paramsType); } catch (Exception e) { e.printStackTrace(); } return null; }}
更多相关文章
- Android(安卓)7.1 根据4G共享动态调整以太网优先级
- android 之摄像头
- Android在内存中读取数据
- 【Android】_MyContentProvider_外部访问接口
- android中的数据库操作
- 仿Android6.0联系人列表
- android前端怎样php后台交互(基础篇)
- Android中ContentProvider详解
- Android(安卓)音频 OpenSL ES PCM数据播放