IPC (Interprocess communication)跨进程通信,是指在两个进程之间交换数据的过程。多进程通信一般分为两种情况。第一种,一个应用因为自身的需要采用多进程实现,比如某些模块由于特殊原因需要运行在单独的进程中。第二种情况,当前应用需要获得其它应用的数据,由于是两个应用,所以必须采用跨进程的方式。下面就对常用的IPC方法做一个总结。
Activity,Service,Receiver都是支持在Intent中传递Bundle的,由于Bundle实现了Parcelable接口,所以他可以在不同进程间传输。我们可以在Bundle中附加数据,并通过Intent传送出去。当然,传送的数据必须是能够被序列化的。关于Android中序列化的知识可以参考http://blog.csdn.net/l664675249/article/details/49403333
A进程把数据写入文件,B进程通过读取这个文件来获得数据。但这这种方法有一个问题就是并发读/写问题。有一个特例,SharedPreferences是Android中提供的轻量级存储方案,底层采用XML实现。但是对于他的读写有一定的缓存策略,因此不建议在进程间通信中使用他。
在MainActivity的onResume中序列化一个对象到sd卡,然后再SecondActivity的onResume中反序列化。关键代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
//MainActivity
private
void
persistToFile() {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
User user =
new
User(
1
,
"hello world"
,
false
);
File dir =
new
File(MyConstants.CHAPTER_2_PATH);
if
(!dir.exists()) {
dir.mkdirs();
}
File cachedFile =
new
File(MyConstants.CACHE_FILE_PATH);
ObjectOutputStream objectOutputStream =
null
;
try
{
objectOutputStream =
new
ObjectOutputStream(
new
FileOutputStream(cachedFile));
objectOutputStream.writeObject(user);
Log.d(TAG,
"persist user:"
+ user);
}
catch
(IOException e) {
e.printStackTrace();
}
finally
{
MyUtils.close(objectOutputStream);
}
}
}).start();
}
//SecondActivity
private
void
recoverFromFile() {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
User user =
null
;
File cachedFile =
new
File(MyConstants.CACHE_FILE_PATH);
if
(cachedFile.exists()) {
ObjectInputStream objectInputStream =
null
;
try
{
objectInputStream =
new
ObjectInputStream(
new
FileInputStream(cachedFile));
user = (User) objectInputStream.readObject();
Log.d(TAG,
"recover user:"
+ user);
}
catch
(IOException e) {
e.printStackTrace();
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
finally
{
MyUtils.close(objectInputStream);
}
}
}
}).start();
}
|
Messenger是一种轻量级的IPC方案,他的底层实现时AIDL。他是以串行的方式处理客户端发来的消息的,一次处理一个请求,因此我们不考虑线程同步问题。
下面是一个例子,客户端向服务端发送一个请求,服务的接到请求后向客户端返回一个消息,Service是注册在另外一个进程中的。
MessengerService
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
public
class
MessengerService
extends
Service {
private
static
final
String TAG =
"MessengerService"
;
private
static
class
MessengerHandler
extends
Handler {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
MyConstants.MSG_FROM_CLIENT:
Log.i(TAG,
"receive msg from Client:"
+ msg.getData().getString(
"msg"
));
Messenger client = msg.replyTo;
Message relpyMessage = Message.obtain(
null
, MyConstants.MSG_FROM_SERVICE);
Bundle bundle =
new
Bundle();
bundle.putString(
"reply"
,
"嗯,你的消息我已经收到,稍后会回复你。"
);
relpyMessage.setData(bundle);
try
{
client.send(relpyMessage);
}
catch
(RemoteException e) {
e.printStackTrace();
}
break
;
default
:
super
.handleMessage(msg);
}
}
}
private
final
Messenger mMessenger =
new
Messenger(
new
MessengerHandler());
@Override
public
IBinder onBind(Intent intent) {
return
mMessenger.getBinder();
}
@Override
public
void
onCreate() {
super
.onCreate();
}
@Override
public
int
onStartCommand(Intent intent,
int
flags,
int
startId) {
return
super
.onStartCommand(intent, flags, startId);
}
}
|
MessengerActivity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public
class
MessengerActivity
extends
Activity {
private
static
final
String TAG =
"MessengerActivity"
;
private
Messenger mService;
private
Messenger mGetReplyMessenger =
new
Messenger(
new
MessengerHandler());
private
static
class
MessengerHandler
extends
Handler {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
MyConstants.MSG_FROM_SERVICE:
Log.i(TAG,
"receive msg from Service:"
+ msg.getData().getString(
"reply"
));
break
;
default
:
super
.handleMessage(msg);
}
}
}
private
ServiceConnection mConnection =
new
ServiceConnection() {
public
void
onServiceConnected(ComponentName className, IBinder service) {
mService =
new
Messenger(service);
Log.d(TAG,
"bind service"
);
Message msg = Message.obtain(
null
, MyConstants.MSG_FROM_CLIENT);
Bundle data =
new
Bundle();
data.putString(
"msg"
,
"hello, this is client."
);
msg.setData(data);
msg.replyTo = mGetReplyMessenger;
try
{
mService.send(msg);
}
catch
(RemoteException e) {
e.printStackTrace();
}
}
public
void
onServiceDisconnected(ComponentName className) {
}
};
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
Intent intent =
new
Intent(
"com.ryg.MessengerService.launch"
);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected
void
onDestroy() {
unbindService(mConnection);
super
.onDestroy();
}
}
|
注:
Service
Client
Messenger以串行的方式处理客户端发来的消息的,一次处理一个请求,如果有大量的并发请求,那么用Messenger就不合适了,需要用AIDL。关于AIDL的讲解请参考http://blog.csdn.net/l664675249/article/details/50649676
ContentProvider是Android中专门用于应用间进行数据共享的方式。详细示例请阅读书本P93.
实现思路,首先在远程Service建立一个TCP服务,然后在主界面中链接TCP服务,连接上后就可以给服务端发消息,服务端随机会随机回应一句话。关于Socket的讲解已经很多了,这里就不在赘述。
IPC方式的优缺点和适用场景
欢迎转载,转载请注明出处http://blog.csdn.net/l664675249/article/details/50654926
转载请注明:Android开发中文站 » Android中常见IPC方法总结