【Android 笔记】IPC 机制

Author Avatar
vecrates 12月 14, 2017

两种用到 IPC 的场景

  • 应用本身需要使用多个进程来实现。 如某些应用需要的内存太大,而系统分配给每个进程的内存有限,所以采用多进程获取更多内存。
  • 应用向其他应用获取需要的数据。 如常见的获取通讯录信息、短信验证码等。

实现 IPC 的方式

  • Intent 附带数据传递
  • 共享文件
  • Messenger
  • Binder
  • ContentProvider
  • Socket

Intetent 实现

 使用 Intetent 启动 Activity、Service、Receiver 可以启动其他进程,然后在其中附带数据即可。 传递的数据必须能够被序列化,即基本类型、实现了 Parcelable 或 Serializable 接口的对象、Android 支持的特殊对象

共享文件

 两个进程共同读写一个文件,实现数据传输。此种方式对数据的格式没有要求。如果存在并发读写,应该注意同步问题
 另外,SharedPreferences 也可以用来进行数据共享,它也属于文件的一种。需要注意的是 SharedPreferences 会在内存中缓存一份,所以得到的文件可能不是最新的。

Messenger 实现

 使用 Messenger 也可以实现进程间的通信,它的底层是以 AIDL 实现。
服务端进程:创建 Handle 对象处理客户端数据,然后生成用其生成 Messenger 对象,在 onBinder() 中返回 Messenger 对象的 Binder。
客户端进程:创建 ServiceConnection 对象,向服务端发送数据。为了能接受服务的发送到客户端的数据,还需创建一个 Handler 对象来处理,并生成 Messenger 对象,然后把 Messenger 对象发送给服务端。
Service:

public class MyService extends Service {

    public final static int RECEIVE_WHAT = 0;
    public final static int REPLY_WHAT = 1;

    private Messenger mReplyMessenger;

    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.v("_v", "service handleMessage");
            switch (msg.what) {
                case RECEIVE_WHAT:
                    Log.v("_v", "客户端消息 " + msg.getData().getString("msg"));
                    mReplyMessenger = msg.replyTo;
                    Message message = Message.obtain();
                    message.what = REPLY_WHAT;
                    Bundle bundle = new Bundle();
                    bundle.putString("msg", "我是服务端!!");
                    message.setData(bundle);
                    try {
                        mReplyMessenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    });


    @Override
    public IBinder onBind(Intent intent) {
        Log.v("_v", "service onBind");
        return mMessenger.getBinder();
    }
}

客户端:

public class MainActivity extends AppCompatActivity {

    private Messenger mMessenger;

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.v("_v", "service onServiceConnected");
            mMessenger = new Messenger(iBinder);
            Message message = Message.obtain(null, MyService.RECEIVE_WHAT);
            Bundle data = new Bundle();
            data.putString("msg", "我是客服端!!");
            message.setData(data);
            // 将Messenger发送给服务器,以便其使用该Messenger回复
            message.replyTo = mServiceReplyMessenger;
            try {
                mMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {}
    };

    private Messenger mServiceReplyMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.v("_v", "activity handleMessage");
            switch (msg.what) {
                case MyService.REPLY_WHAT:
                    Log.v("_v", "服务器回复 " + msg.getData().getString("msg"));
                    break;
            }
        }
    });

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        unbindService(mServiceConnection);
        super.onDestroy();
    }
}

AIDL 实现

另一篇,AIDL 实现 IPC

ContentProvider 实现

另一篇,ContentProvider 及其实现 IPC

Socket 实现

Socket 是客户端与服务器通信的一种方式,它具有和其他进程通信的功能。
Socket 有两种类型,StreamSocket(流套接字)和 DatagramSocket(用户数据报套接字),前者基于 TCP 协议,后者基于 UDP 协议。

几种方式的对比

名称 优点 缺点 适用场景
Bundle 简单 只支持 Bundle 支持的类型 四大组件之间通信
文件 简单 不适合高并发,不能即时通信 无并发,数据简单,不需要即时
AIDL 功能强大,高并发,即时通信 使用复杂,需要处理好同步 一对多通信 + RPC
Messenger 一对多通信,即时通信 处理不好高并发,不支持 RPC,只支持 Bundle 支持的数据 低并发,即时通信,无 RPC
ContentProvider 一对多并发,可扩展 受约束的 AIDL 一对多进程间数据共享
Socket 网络传输,一对多并发即时通信 繁琐,不支持 RPC 网络数据交换