Android的跨进程通信(IPC)是一整套的知识体系,研究透IPC的话,应该也是Android开发中的进阶选手了!不想当将军的老师不是个好厨子。在工作闲暇之余我希望系统学习一下Android的IPC机制。好了废话少说!
首先需要知晓的是Android中的进程的含义。这是个之前让我一直琢磨不透的问题。根据虚拟机的解释是这样的,系统会为每个进程开辟一个独立的虚拟机,但是一个应用可以存在多进程,所以我们就可以解释Android app中的应用间的跳转了。
在android 中默认通过包名来区分进程,但也存在一个app有多进程,多进程运行模式通过在AndroidManifest.xml的四大组件中运用process指定进程,默认是一个App一个进程

<service
            android:name=".ipc.IpcService"
            android:enabled="true"
            android:exported="true"
            android:process=":second" />

android:process=”:second”这句话就新建指定了com.XXX:second进程。
理解了多进程模式后,我们就可以来试试多进程通信了。哈哈哈哈。

再者就是对象的序列化以及反序列化了。以往我在这方面的印象只停留在在网络通信方面的将Json文件转化为可序列化的对象,其实在序列化的意思就是将一个流的数据转化为一个特定的类的对象,注意是对象。序列化的实现机制在Java中是通过实现Serializable接口,而在Android是通过实现Parceable接口。在Serializable的实现方法中有一个serialVersionUID这个long变量值,它的作用是方便能够反序列化,只有校对了这个serialVersionUID值才可以进行反序列化。在Android的实现方式上则是通过以下代码实现序列化以及反序列化的。

//序列化
public static final Parcelable.Creator<Book> CREATOR=new        Parcelable.Creator<Book>(){
        @Override
        public Book createFromParcel(Parcel source) {
            return new Book(source);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };
//反序列化
 @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }

至于Parcel这个类的详细理解,我不是很懂,还望大家赐教。

在Android中IPC大致有这么几种方式:
1. 使用Bundle传输数据,其实本质上就是通过Intent来跨进程通信的,因为Activity可能对应不同的进程,所以Intent是实现了IPC的,至于这其中的原理,有待深究。
2. 文件共享的方式,两个进程通过读写同一个文件来进行数据交换的方式。但是这种方式是进程不安全的,如果存在并发的读写操作,后果很严重。因此这种方式一般适合于数据同步要求不高的情况!而SharedPreference的方式就更加不适合进程间的通信了,即使SharedPreference方式本质上也是文件的方式,但由于Android对它的在内存中有一定的缓存策略,那么系统对它的读写就变得不可靠!
3. 使用Messager信使,这也是本文重点介绍的
4. 使用AIDL的方式进行通信
5. 使用ContentProvider共享数据
6. 使用Socket,这也是Java的一种方式

Messager方式是一种Binder机制的轻量级实现,其实底层实现与AIDL的方式一样都是基于Binder的实现。因为它对AIDL做了封装,Messager的使用方法很简单。

首先是服务端进程:
在服务端创建一个service来处理客户端的连接请求,同时创建一个Handler并通过它来创建一个Messager信使,然后在Service的onBind中返回这个Messager对象底层的Binder即可以在Handler中接收到客户端的连接请求消息了

public class IpcService extends Service {

    private static final String TAG="IpcService";

    public IpcService() {
    }

    private static class ServiceHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case Contants.MSG_FROM_CLIENT:
                    Log.e(TAG, "recevie msg from client"+msg.getData().getString("msg") );
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }


    private final Messenger mMessenger=new Messenger(new ServiceHandler());

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mMessenger.getBinder();
    }
}

然后是客户端进程
首先要绑定服务端的service,绑定连接成功后,通过返回的IBinder对象创建一个Messager对象,再通过这个Messager对象给服务端发送Message。区别Messager与Message这两个类,Messager是邮差的角色。

public class ClientActivity extends AppCompatActivity {
    private Messenger mServices;

    private static final String TAG="ClientActivity";
//连接
    private ServiceConnection mConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mServices=new Messenger(service);
            Message message=Message.obtain(null,Contants.MSG_FROM_CLIENT);
            Bundle data=new Bundle();
            data.putString("msg","hello this is client");
            message.setData(data);
            try {
                mServices.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        Intent in=new Intent(this,IpcService.class);
        bindService(in,mConnection,BIND_AUTO_CREATE);//通过mConnection回调绑定服务端的服务
    }

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

自此Messager的简单用法就已经完结了!在打印的log信息中我们可以看到“hello,this is client”。下面会继续深究AIDL方式。