Android跨进程通信的方式大概有如下几种:
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" );
startActivity(callIntent);
Android应用程序可以使用文件或SqlLite数据库来存储数据。
Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据),
应用程序可以利用Content Provider完成下面的工作
1. 查询数据
2. 修改数据
3. 添加数据
4. 删除数据
Intent intent = new Intent(“com.android.ACTION_TEST”);
intent.putExtra("value","content");
mContext.sendBroadcast(intent);
客户端LocalSocket代码
//创建对象
LocalSocket localSocket = new LocalSocket();
//连接socketServerSocket
localSocket.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;
}
}
这也是本文采取的主要方式,通过AIDL读取共享内存的方式去实现大数据的传输
5.1首先定义两个AIDL文件,注意服务端和客户端的两个文件要一样,并且放在同一个文件夹下。
服务端使用
package com.example.administrator.testgsensor;
import com.example.administrator.testgsensor.ITestCallbackAidlInterface;
// Declare any non-default types here with import statements
interface ITestAidlInterface {
void registerCallback(ITestCallbackAidlInterface cb);
void unregisterCallback(ITestCallbackAidlInterface cb);
ParcelFileDescriptor getMemoryFileDescriptor();
void serverSendData(String data);
}
客户端使用
// ITestCallbackAidlInterface.aidl
package com.example.administrator.testgsensor;
// Declare any non-default types here with import statements
interface 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;
}
}