天天看点

【Android开发艺术探索】IPC机制(三)-使用Messenger进行跨进程通信

使用Messenger进行跨进程通信

  • 翻译为中文就是信息的意思,通过它可以在不同进程中传递Message对象,是一种轻量级的IPC方案。底层是AIDL。通过源代码容易看出来。
构造方法A:
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
    构造方法B:
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
           

判断两个Messenger是不是相等:

/**
     * Comparison operator on two Messenger objects, such that true
     * is returned then they both point to the same Handler.
     */
    public boolean equals(Object otherObj) {
        if (otherObj == null) {
            return false;
        }
        try {
            return mTarget.asBinder().equals(((Messenger)otherObj)
                    .mTarget.asBinder());
        } catch (ClassCastException e) {
        }
        return false;
    }
           
  • 一次只能处理一个请求。服务端不存在并发执行的情形。
  • Message对象的obj字段在2.2之前不能进行跨进程传输,在2.2之后,只能传输那些系统实现了Parcelable的对象,自定义的实现Parcelable的对象不能传输。所以我们使用它的setData方法。
  • Messenger工作原理
  • 【Android开发艺术探索】IPC机制(三)-使用Messenger进行跨进程通信
  • 具体代码实现:

    一个服务,作为服务端:

package com.example.ipc.messager;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

/**
 * 充当服务器端,这个服务运行在一个新的进程中
 * 客户端远程跨进程通信
 */
public class ServerService extends Service {
    private static final int FROM_CLIENT = ;
    private Messenger messenger = new Messenger(new ServiceHandler());
    public ServerService() {
    }

    class ServiceHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case FROM_CLIENT:
                    Log.d("666","服务器端收到客户端数据:"+msg.getData().getString("data"));
                    Messenger client = msg.replyTo;
                    Message obtain = Message.obtain(null, );
                    Bundle bundle = new Bundle();
                    bundle.putString("data","我是服务端");
                    obtain.setData(bundle);
                    obtain.replyTo = messenger;
                    try {
                        client.send(obtain);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;

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

一个Activity充当客户端:

package com.example.ipc.messager;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.example.administrator.testfortemplate.R;

public class ClientActivity extends AppCompatActivity {

    private static final int FROM_SERVER = ;
    private final Messenger activityMessager = new Messenger(new ActivityHandler());
    class ActivityHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case FROM_SERVER:
                    Log.d("666","客户端收到服务器端数据:"+msg.getData().getString("data"));
                    Messenger client = msg.replyTo;
                    Message obtain = Message.obtain(null,);
                    Bundle bundle = new Bundle();
                    bundle.putString("data","Hi:我是客户端");
                    obtain.setData(bundle);
                    obtain.replyTo = activityMessager;
                    try {
                        client.send(obtain);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        bindService(new Intent(this,ServerService.class),new MyConnection(),BIND_AUTO_CREATE);
    }

    class MyConnection implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Messenger messenger = new Messenger(service);
            Message obtain = Message.obtain(null, );
            Bundle bundle = new Bundle();
            bundle.putString("data","我是客户端");
            obtain.setData(bundle);
            obtain.replyTo = activityMessager;
            try {
                messenger.send(obtain);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}
           

清单文件:

<service
            android:name="com.example.ipc.messager.ServerService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote"></service>
           

设置了process两者才是不在同一个进程中。否则这个例子就不是跨进程通信了。具体原因见【Android开发艺术探索】IPC机制(一)