前言:今天学习了进程间的通信,感觉实现比较繁琐的,于是在这记录一篇如何实现进程间的通信。
补充:
本地服务:运行在自己应用里的服务。
远程服务:运行在其他应用里的服务(可以实现进程间通信 ipc(Inter-Process
Communication))
andoid IPC方式主要有以下几种:
1.bundle :
简单易用 但是只能传输Bundle支持的对象 常用于四大组件间进程间通信
2.文件共享:
简单易用 但不适合在高并发的情况下 并且读取文件需要时间 不能即时通信 常用于并发程度不高 并且实时性要求不高的情况
3.AIDL :
功能强大 支持一对多并发通信 支持即时通信 但是使用起来比其他的复杂
需要处理好多线程的同步问题 常用于一对多通信 且有RPC 需求的场合(服务端和客户端通信)
4.Messenger :
功能一般 支持一对多串行通信 支持实时通信 但是不能很好处理高并发情况只能传输Bundle支持的类型 常用于低并发的无RPC需求一对多的场合
5.ContentProvider :
在数据源访问方面功能强大 支持一对多并发操作 可扩展call方法 可以理解为约束版的AIDL 提供CRUD操作和自定义函数 常用于一对多的数据共享场合
6.Socket :
功能强大 可以通过网络传输字节流 支持一对多并发操作 但是实现起来比较麻烦 不支持直接的RPC 常用于网络数据交换
总结起来
当仅仅是跨进程的四大组件间的传递数据时 使用Bundle就可以 简单方便
当要共享一个应用程序的内部数据的时候 使用ContentProvider实现比较方便 当并发程度不高 也就是偶尔访问一次那种 进程间通信 Messenger就可以 当设计网络数据的共享时 使用socket 当需求比较复杂 高并发 并且还要求实时通信 而且有RPC需求时 就得使用AIDL了
文件共享的方法用于一些缓存共享 之类的功能
现在有个需求:在第一个应用的服务中有个方法,要求你在带二个应用中点击按钮调用第一个服务的方法。
通过上面的需求我们来做个简单的demo来实现进程间的通信。
一 首先建立两个安卓工程:
(AIDLDemo1 的app name取名字 为远程服务)

(AIDLDemo2 的app name取名字 为本地服务)

二 本地服务中
1 建立一个服务取名RemoteService(清单文件别忘了注册下服务)
在本地服务中定义一个方法(远程服务中要操作的方法)通过接口(自定义个)暴露出去。

2 定义类MyBind 继承Binder 实现你定义的接口(由于写到后面需要修改此处。 此处逻辑为基本逻辑不再粘贴)
3 返回接口实现子类的对象

二 远程服务中进行绑定服务
1 声明Intent对象
Intent intent = new Intent();
// 此处 (this,远程服务的类名.class)是行不通的(因为远程服务的类名.class 本应用中没有的) 通过下面的可以 intent.setAction("com.example.administrator.aidldemo1.RemoteService");
注 此action为远程服务中服务注册时配的Intent-fliter中配的自定义action
2 绑定服务
bindService(intent, conn,BIND_AUTO_CREATE);
private class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
* 3 拿中间人对象
* */
iinterface = Iinterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onDestroy() {
// 解绑的逻辑(不解绑会报错)
unbindService(conn);
super.onDestroy();
}
3 onServiceConnected 中:
/*链接成功获得中间人对象 但是此时不是同一个应用Iservice对象在此处使用不了
* aidl技术孕育而生 解决此困难(一种语言专门解决进程间的通信)
实现步骤:
1 到远程进程的App中 找到你定义的接口 进行鼠标右键show in explorer
把接口的.java文件 改为.aidl (带public 都去掉 本语言本身就是 公开通信本来就是public)

2 此时你的自定义MyBind类会报错
* 此时系统会自动生成一个文件Iservice.java 内部有Stub类 继承了
Bined 实现了Iservice
* 你只需要吧报错的自定义类直接继承Stub即可(注: 此处studio不会自动升成R文件还需这样处理后再继承Stub:
在你的module的main下面新建一个aidl文件夹,如图

在这个aidl文件夹下面新建一个包,包名必须和你的AndroidManifest.xml中package的包名相同。然后把你的aidl文件放入到这个包下。
(此处我把原来的aidl文件复制走一份到此包下)

然后rebuild一下就可以在build/source/aidl/debug/下生成了相对应的.java文件了


此时 MyBind 可以继承Stub类了
(As中必须这样处理否则你是用不了这个类的 不会自动生成 eclipse会子动生成.java文件)

3
保证两个应用有同一个aidl文件(在本地服务中建立一个与远程服务相同包的文件夹 把aidl文件和.java(Iinterface)拷贝过来)

4 此时就可以使用中间人对象了

5 按钮中调用方法

6 特别注意 在远程服务中注册服务时要配置 自定义个action

运行结果:



经过一番的折腾终于成功了,虽然输出的结果很简单,但是现在你已经初步学会了如何搭载进行进程间的通信。
在完成中也遇到了一点麻烦 参考链接:http://blog.csdn.net/suncold123/article/details/48785709感谢这位大大的文章。
网友评论