Android中常见IPC方法总结

来源:互联网 发布:淘宝泰州医药城地址 编辑:程序博客网 时间:2024/05/19 13:15

IPC (Interprocess communication)跨进程通信,是指在两个进程之间交换数据的过程。多进程通信一般分为两种情况。第一种,一个应用因为自身的需要采用多进程实现,比如某些模块由于特殊原因需要运行在单独的进程中。第二种情况,当前应用需要获得其它应用的数据,由于是两个应用,所以必须采用跨进程的方式。下面就对常用的IPC方法做一个总结。

使用Bundle

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
 privatevoid persistToFile() {
        newThread(newRunnable() {
 
            @Override
            publicvoid run() {
                User user = newUser(1"hello world"false);
                File dir = newFile(MyConstants.CHAPTER_2_PATH);
                if(!dir.exists()) {
                    dir.mkdirs();
                }
                File cachedFile = newFile(MyConstants.CACHE_FILE_PATH);
                ObjectOutputStream objectOutputStream = null;
                try{
                    objectOutputStream = newObjectOutputStream(
                            newFileOutputStream(cachedFile));
                    objectOutputStream.writeObject(user);
                    Log.d(TAG, "persist user:"+ user);
                catch(IOException e) {
                    e.printStackTrace();
                finally{
                    MyUtils.close(objectOutputStream);
                }
            }
        }).start();
    }
 
//SecondActivity
  privatevoid recoverFromFile() {
        newThread(newRunnable() {
 
            @Override
            publicvoid run() {
                User user = null;
                File cachedFile = newFile(MyConstants.CACHE_FILE_PATH);
                if(cachedFile.exists()) {
                    ObjectInputStream objectInputStream = null;
                    try{
                        objectInputStream = newObjectInputStream(
                                newFileInputStream(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

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
publicclass MessengerService extends Service {
 
    privatestatic final String TAG = "MessengerService";
 
    privatestatic class MessengerHandler extendsHandler {
        @Override
        publicvoid handleMessage(Message msg) {
            switch(msg.what) {
            caseMyConstants.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 = newBundle();
                bundle.putString("reply""嗯,你的消息我已经收到,稍后会回复你。");
                relpyMessage.setData(bundle);
                try{
                    client.send(relpyMessage);
                catch(RemoteException e) {
                    e.printStackTrace();
                }
                break;
            default:
                super.handleMessage(msg);
            }
        }
    }
 
    privatefinal Messenger mMessenger = new Messenger(new MessengerHandler());
 
    @Override
    publicIBinder onBind(Intent intent) {
        returnmMessenger.getBinder();
    }
 
    @Override
    publicvoid onCreate() {
        super.onCreate();
    }
 
    @Override
    publicint onStartCommand(Intent intent, intflags, intstartId) {
        returnsuper.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
publicclass MessengerActivity extends Activity {
 
    privatestatic final String TAG = "MessengerActivity";
 
    privateMessenger mService;
    privateMessenger mGetReplyMessenger = newMessenger(newMessengerHandler());
 
    privatestatic class MessengerHandler extendsHandler {
        @Override
        publicvoid handleMessage(Message msg) {
            switch(msg.what) {
            caseMyConstants.MSG_FROM_SERVICE:
                Log.i(TAG, "receive msg from Service:"+ msg.getData().getString("reply"));
                break;
            default:
                super.handleMessage(msg);
            }
        }
    }
 
    privateServiceConnection mConnection = newServiceConnection() {
        publicvoid onServiceConnected(ComponentName className, IBinder service) {
            mService = newMessenger(service);
            Log.d(TAG, "bind service");
            Message msg = Message.obtain(null, MyConstants.MSG_FROM_CLIENT);
            Bundle data = newBundle();
            data.putString("msg""hello, this is client.");
            msg.setData(data);
            msg.replyTo = mGetReplyMessenger;
            try{
                mService.send(msg);
            catch(RemoteException e) {
                e.printStackTrace();
            }
        }
 
        publicvoid onServiceDisconnected(ComponentName className) {
        }
    };
 
    @Override
    protectedvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_messenger);
        Intent intent = newIntent("com.ryg.MessengerService.launch");
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
 
    @Override
    protectedvoid onDestroy() {
        unbindService(mConnection);
        super.onDestroy();
    }
}

注:
Service

  • Service中有一个Handler,用来处理Client发来的消息,并在Handler中新建一个Messenger client = msg.replyTo来向客户端返回消息。
  • 在onBind中返回他里面的Binder对象

Client

  • 为了接收服务端的消息,客户端也需要准备一个接收消息的Messenger和Handler。
  • msg.replyTo = mGetReplyMessenger,当客户端发送消息的时候,需要把接收服务端回复的Messenger通过Message的replyTo参数传给服务端。

AIDL

Messenger以串行的方式处理客户端发来的消息的,一次处理一个请求,如果有大量的并发请求,那么用Messenger就不合适了,需要用AIDL。关于AIDL的讲解请参考http://blog.csdn.net/l664675249/article/details/50649676

ContentProvider

ContentProvider是Android中专门用于应用间进行数据共享的方式。详细示例请阅读书本P93.

Socket

实现思路,首先在远程Service建立一个TCP服务,然后在主界面中链接TCP服务,连接上后就可以给服务端发消息,服务端随机会随机回应一句话。关于Socket的讲解已经很多了,这里就不在赘述。

总结

IPC方式的优缺点和适用场景

优缺点

欢迎转载,转载请注明出处http://blog.csdn.net/l664675249/article/details/50654926

转载请注明:Android开发中文站 » Android中常见IPC方法总结

0 0
原创粉丝点击