天天看点

Android 利用Messenger进行跨进程通信

Messenger通信原理

Messenger其实是谷歌对aidl进行的封装,用来处理简单的跨进程通信。那么如何用Messenger传递信息呢?

单向通信

现在假设我们有服务端和客户端,并且服务端与客户端不在同一进程中。

     首先服务端需要创建一个Handler用来接收客户端发送来的消息,然后利用这个handler,来构造一个Messenger,并且在onBind方法中将messenger的IBinder返回给客户端。那么当客户端通过bindService方法绑定这个服务之后,就可以通过这个IBinder对象来构造一个Messenger对象,然后就可以发送Message类型的消息,从而实现一个单向跨进程通信。

这么说可能有些抽象,下面我贴上实现代码,看完就应该很容易理解了。

//服务端代码

RemoteService.class

public class RemoteService extends Service {
    private static final String TAG = "RemoteService";
    private Handler receiveHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    Log.d(TAG,"收到了客户端发来的消息:" + msg.getData().getString("client_message"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
    //这里利用一个Handler对象构造一个Messenger对象
    private Messenger messenger = new Messenger(receiveHandler);
    public RemoteService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}
           

这里要注意,由于演示的是跨进程通信,但是为了方便我并没有写两个应用,而是在service的配置中开了一个进程

AndroidManifest.xml

<service
            android:process=":remote"
            android:name=".service.RemoteService"
            android:enabled="true"
            android:exported="true"></service>
           

//客户端代码

MainActivity.class

public class MainActivity extends AppCompatActivity {

    private Messenger messenger;
    private ServiceConnection mConnection = new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //这里利用一个IBinder对象构造一个Messenger对象
            messenger = new Messenger(service);
            Message msg = Message.obtain(null, 0);
            Bundle bundle = new Bundle();
            bundle.putString("client_message","I'm from Client!");
            msg.setData(bundle);
            try {
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Intent intent = new Intent(this, RemoteService.class);

        //绑定服务按钮
        Button btnBind = (Button) findViewById(R.id.btn_bind);
        btnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService(intent, mConnection, BIND_AUTO_CREATE);
            }
        });
    }
}
           

当我们点击绑定服务按钮时,控制台就会输出一条信息:

D/RemoteService: 收到了客户端发来的消息:I'm from Client!。

下面说一下双向通信:

    要实现双向通信,那么客户端也需要创建一个Handler对象来接收服务端发来的消息。

        然后同样,利用这个Handler对象来构造一个Messenger对象,并且在给服务端发消息时,

给Message对象的replyTo属性赋值,也就是msg.replyTo = clientMessenger;

那么服务端如何给客户端发消息呢?

其实很容易,就是利用刚才的msg.replyTo来获取客户端Messenger,然后发送消息。

    双向通信代码(跨进程)

//服务端代码

RemoteService.class

public class RemoteService extends Service {
    private static final String TAG = "RemoteService";
    private Handler receiveHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    Log.d(TAG,"收到了客户端发来的消息:" + msg.getData().getString("client_message"));
                    //在这里得到客户端的Messenger
                    Messenger clientMessenger = msg.replyTo;
                    Message msg1 = Message.obtain(null, 0);
                    Bundle bundle = new Bundle();
                    bundle.putString("server_message","I'm from Server!");
                    msg1.setData(bundle);
                    try {
                        clientMessenger.send(msg1);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    private Messenger messenger = new Messenger(receiveHandler);
    public RemoteService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}
           

//客户端代码

MainActivity.class

public class MainActivity extends AppCompatActivity {

    private Messenger messenger;
    private ServiceConnection mConnection = new ServiceConnection(){
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //这里利用一个IBinder对象构造一个Messenger对象
            messenger = new Messenger(service);
            Message msg = Message.obtain(null, 0);
            Bundle bundle = new Bundle();
            bundle.putString("client_message","I'm from Client!");
            msg.setData(bundle);
            //这里就是把客户端的Messenger传递过去
            msg.replyTo = clientMessenger;
            try {
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private Handler clientHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    Log.d("MainActivity","收到了服务端传回的消息:"+msg.getData().getString("server_message"));
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    private Messenger clientMessenger = new Messenger(clientHandler);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final Intent intent = new Intent(this, RemoteService.class);

        //绑定服务按钮
        Button btnBind = (Button) findViewById(R.id.btn_bind);
        btnBind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService(intent, mConnection, BIND_AUTO_CREATE);
            }
        });
    }
}
           

当我们点击绑定服务按钮时,控制台就会输出这两条信息:

D/RemoteService: 收到了客户端发来的消息:I'm from Client!。

D/MainActivity: 收到了服务端传回的消息:I'm from Server!

继续阅读