使用Messenger进行跨应用(进程)通讯

使用Messenger进行跨进程通讯

Messenger可以翻译为信使,使用它我们可以进行跨进程通讯.Messengers是一种轻量的IPC,通过构造方法可以轻松的看出它的底层是现实AIDL.

public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

Messenger的使用方法很简单

服务端

需要在服务端创建一个Service,来处理客户端的连接请求,同时创建一个Handler来处理接受到的消息,然后在通过Handler创建一个Messenger对象,最后在Service的onBind()方法中返回Messenger的Binder对象即可.

package com.lixxy.service;

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.support.annotation.Nullable;
import android.util.Log;

public class MessengerService extends Service {
    
    private static final String TAG = "MessengerService";
    private final Messenger mMessenger = new Messenger(new MessengerHandler());
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "连接了");
        return mMessenger.getBinder();
    }
    
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 100:
                    //获取client发送的消息
                    Log.e(TAG, msg.getData().getString("client"));

                    //收到消息后给client发送消息
                    Messenger client = msg.replyTo;
                    Message message = Message.obtain();
                    Bundle bundle = new Bundle();
                    bundle.putString("service", "Hello,Client");
                    message.setData(bundle);
                    message.what = 200;
                    try {
                        client.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
}

服务端的service配置

在AndroidManifest中加入

<!--permission可加可不加,如果加上的话,在cleint中也要加上-->
<service android:name=".MessengerService"
    android:exported="true"
    android:permission="com.lixxy.client.service">
</service>

客户端

首先要绑定服务端的service,然后在ServiceConnection中就可以通过IBinder发送消息.

@Override
//bind方法需要三个参数,intent,ServiceConnection,flags
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

//Intent 
//由于服务端和客服端是两个APP,所以不能通过Intent intent = new //Intent(this,MessengerService.class);获取Intent
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.lixxy.service","com.lixxy.service.MessengerService"));

//private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Messenger messenger = new Messenger(service);

            Bundle bundle = new Bundle();
            bundle.putString("client", "Hello,Services");

            Message message = Message.obtain();
            message.what = 100;
            message.setData(bundle);
            //如果客户端同时要接受服务器发的消息,需要加这句
            message.replyTo = mMessenger;
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "连接失败");
        }
    };

如果客户端同时要接受服务器发的消息,也要创建一个Handler处理消息,然后通过这个Handler来创建Messenger对象.

完整的客户端代码如下

package com.lixxy.client;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.nfc.Tag;
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 android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity";
    private final Messenger mMessenger = new Messenger(new MessengerHandler());
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 200:
                    //获取service发送的消息
                    Log.e(TAG, msg.getData().getString("service"));

                    break;
            }


        }
    }

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

        Button button = findViewById(R.id.mBtnBind);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //由于服务端和客服端是两个APP,所以不能通过
                // Intent intent = new //Intent(this,MessengerService.class)获取Intent
                Intent intent = new Intent();
                intent.setComponent(new ComponentName("com.lixxy.service", "com.lixxy.service.MessengerService"));
                bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
            }
        });

    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Messenger messenger = new Messenger(service);

            Bundle bundle = new Bundle();
            bundle.putString("client", "Hello,Services");

            Message message = Message.obtain();
            message.what = 100;
            message.setData(bundle);
            //如果客户端同时要接受服务器发的消息,需要加这句
            message.replyTo = mMessenger;
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "连接失败");
        }
    };

}

注意:如果服务端的service中加了android:permission:“xxx.xxx.xxx”,那么在客户端的AndroidManifest也要加入权限,不然会报错Not allowed to bind to service Intent

<permission android:name="com.lixxy.client.service" />
<uses-permission android:name="com.lixxy.client.service" />

Demo地址

https://github.com/Lillls/MessengerDemo

你可能感兴趣的:(个人笔记)