Android系统中应用程序之间不能共享内存,在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。
1、其中Activity可以跨进程调用其他应用程序的Activity
2、Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),,当然,也可以对其他应用程序的数据进行增、删、改操 作
3、Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播,采用的是被动接收的方法,客户端只能接收广播数据,而不能向发送广播的程序发送信息。
4、Service和Content Provider类似,也可以访问其他应用程序中的数据,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务,AIDL Service可以将程序中的某个接口公开,这样在其他的应用程序中就可以象访问本地对象一样访问AIDL服务对象了。
这4种跨进程通讯的方式可以应用在 不同的场合,例如,在需要显示可视化的界面时可以用Activity,需要返回记录集时可以用ContentProvider。
方式一:访问其他应用程序的Activity
Activity既可以在进程内(同一个应用程序)访问,也可以跨进程访问。如果想在同一个应用程序中访问Activity,需要指定Context对象和Activity的Class对象,代码如下:
Intent intent = new Intent(this , Test.class );
startActivity(intent);
Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。
在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(“tel:12345678” );
startActivity(callIntent);
执行上面的代码后,系统会自动拨号。
方式二:Content Provider
Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作
- 查询数据
- 修改数据
- 添加数据
- 删除数据
虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。
Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。
对于访问Content Provider的程序,需要使用ContentResolver对象。该对象需要使用getContentResolver方法获得,代码如下:
ContentResolver cr = getContentResolver();
与Activity一样,Content Provider也需要与一个URI对应。每一个Content Provider可以控制多个数据集,在这种情况下,每一个数据集会对应一个单独的URI。所有的URI必须以“content://”开头。
方式三:广播(Broadcast)
广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。
在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。
- 静态广播
接收广播必须在AndroidManifest.xml文件中注册 receiver。下面来编写一个接收广播的应用程序。首先建立一个android工程:receiver。然后编写一个MyReceiver类,该类是 BroadcastReceiver的子类。 - 动态广播
需要注册和解除注册
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction("con.screen.ACTION1");
context.registerReceiver(mBroadcastReceiver, myIntentFilter);
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
}
}
方式四:AIDL服务
服务(Service)是android系统中非常重要的组件。Service可以脱离应用程序运行。也就是说,应用程序只起到一个启动Service的作用。一但Service被启动,就算应用程序关闭,Service仍然会在后台运行。
android系统中的Service主要有两个作用:后台运行和跨进程通讯。后台运行就不用说了,当Service启动后,就可以在Service对象中 运行相应的业务代码,而这一切用户并不会察觉。而跨进程通讯是这一节的主题。如果想让应用程序可以跨进程通讯,就要使用我们这节讲的AIDL服 务,AIDL的全称是Android Interface Definition Language,也就是说,AIDL实际上是一种接口定义语言。通过这种语言定义接口后,Eclipse插件(ODT)会自动生成相应的Java代码接 口代码。
Socket
socket也叫套接字,分为流式套接字(TCP)和用户数据报套接字(UDP)
Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。
基于TCP协议的Socket:
服务器端首先声明一个ServerSocket对象并且指定端口号,然后调用Serversocket的accept()方法接收客户端的数据。accept()方法在没有数据进行接收的处于堵塞状态。(Socketsocket=serversocket.accept()),一旦接收到数据,通过inputstream读取接收的数据。
客户端创建一个Socket对象,指定服务器端的ip地址和端口号(Socketsocket=newSocket(“172.168.10.108”,8080);),通过inputstream读取数据,获取服务器发出的数据(OutputStreamoutputstream=socket.getOutputStream()),最后将要发送的数据写入到outputstream即可进行TCP协议的socket数据传输。
名称 | 优点 | 缺点 | 适用场景 |
Bundle | 简单易用 | 只能传输Bundle支持的数据类型 | 四大组件间的进程间通信 |
AIDL | 支持一对多并发通信,支持实时通信 | 使用复杂,需处理线程同步 | 一对多通信,并发通信,有RPC需求 |
Messenger | 支持一对多串行通信,使用起来比AIDL简单 | 不支持并发,不支持RPC,只能传输Bundle支持的类型 | 一对多通信,服务端不存在并发执行的情景(即多进程单线程),无RPC需求或者无需要返回结果的RPC需求 |
ContentProvider | 受约束的AIDL,支持一对多并发通信,提供了统一的uri与统一的接口,方便通信 | 一般只提供CRUD操作 | 一对多通信,并发通信,有RPC需求 |
文件共享 | 简单易用 | 不支持并发,无法实时通信 | 无并发,适用于交换简单的数据实时性不高的情景 |
socket | 支持一对多并发通信,支持实时通信 | 使用复杂 | 网络数据交换 |
相关参考
android中跨进程通讯的4种方式
图文详解 Android Binder跨进程通信机制 原理