多进程间通信Messenger使用

Messenger 信使 也是进程间通信的一种方式,但是它的好处在于不用像aidl 一样必须要定义aidl 接口,然后通过接口来通信,本质上messenger 的实现底层也是通过aidl 实现的。

实现原理是客户端通过绑定服务端service ,通过返回的IBundle,生成获取到服务端的Messenger对像,然后通过服务端的Messenger 对象将客户端的Messenger 发送到服务端,这样两端各自持有对方的Messenger 对像,而每个messenger 都会绑定各自的handler对象,所以当发送消息时handler 就会收到,然后就可以愉快的通信了。

本篇代码将和上篇aidl 使用相同的项目多进程间通信AIIDL使用

步骤如下:

1.服务端 新建两个项目,一个用于服务端app (aidlapplication),一个用于客户端app(clientservice)

2.服务端 创建服务端service ,创建Messenger 并通过getBinder获取 IBinder ,使用onBind返回给客户端

3.客户端绑定服务端service,通过IBinder 获取到服务端Messenger

4.将客户端的Messenger 发送到服务端

5.两端可以互相发送消息了

 

1.服务端 新建两个项目,一个用于服务端app (aidlapplication),一个用于客户端app(clientservice)

 这步就不多说了,名字大家可以随意取,这里只是便于分辩

2.服务端 创建服务端service ,创建Messenger 并通过getBinder获取 IBinder ,使用onBind返回给客户端

public class MessengerService extends Service {
    private static final String TAG = "MessengerService";
    Messenger clientMessenger;
    int messageid=0;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
    Handler handler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what==0) {
                //获取客户端的messenger对象,及初始消息
                clientMessenger=msg.replyTo;
            }else {
                Bundle bundle=msg.getData();
                Log.d(TAG, msg.what +"" + "handleMessage: 收到客户端的消息"+ bundle.getString("ms"));

                //发送消息给客户端我收到你的消息了
                Bundle sbundle=new Bundle();
                Message message=Message.obtain();
                sbundle.putString("cms","这是一条服务端发来的消息" + messageid++);
                message.setData(sbundle);
                message.what=0x02;
                try {
                    clientMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

        }
    };
    //创建服务端的messenger 对象
    Messenger messenger=new Messenger(handler);
}

这里我们通过onBind 返回了一个IBinder 接口 ,实际是从Messenger中获取到的IBinder 接口,而Messenger 本身在初始化时又绑定了一个handler ,当客户端发送消息时服务端的handler 就会收到消息,replyTo 方法用于获取客户端的Messenger对象。

很重要的一点,服务端要注册

 <service
            android:name=".MessengerService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <action android:name="com.example.service.messenger"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

3.客户端绑定服务端service,通过IBinder 获取到服务端Messenger

 通过intent 绑定服务

 Intent intent = new Intent();
        intent.setPackage("com.example.aidlapplication");
        intent.setAction("com.example.service.messenger");
        bindService(intent, connection, BIND_AUTO_CREATE);

这里的package是服务端的包名,action 是注册时定义的,用于匹配启动绑定服务。

 ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            serviceMessenger = new Messenger(service);
            if (serviceMessenger == null) {
                try {
                    throw new IllegalAccessException("绑定成功但是 serviceMessenger 是 null");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }


        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

绑定成功后我们获取到了,服务端的Messenger对象serviceMessenger

4.将客户端的Messenger 发送到服务端

 通过绑定获取到了服务端的Messenger对象serviceMessenger 然后通过这个serviceMessenger 将客户端的messenger 发送到

服务端。

这里需要客户端先new 一个Messenger  cMessenger然后绑定一个handler .

 Message message = Message.obtain();
                message.what = 0x00;
                message.replyTo = cMessenger;
                Bundle bundle=new Bundle();
                message.setData(bundle);
                try {
                    //发送客户端Messenger 到服务端,本意在建立链接
                    serviceMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

5.两端可以互相发送消息了

通过上边的步骤我们两个端各自获取到了对方的Messenger 对象,就可以通过这个发送消息到对方了。

我将客户端的activity 全部粘出来

public class MessageActivity extends Activity {
    StringBuilder stringBuilder=new StringBuilder();
    private static final String TAG = "MessageActivity";
    private Button mMessengerBindService;
    private Button mMessengerSendMsToService;
    private TextView mmessengerMsShow;
    private Button messenger_send_messenger_to_service;
    private Button messengerSendMsToService;
    private TextView messengerMsShow;
    Messenger serviceMessenger;
    Handler serviceHandler;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mesenge_layout);
        initView();
        Intent intent = new Intent();
        intent.setPackage("com.example.aidlapplication");
        intent.setAction("com.example.service.messenger");
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            serviceMessenger = new Messenger(service);
            if (serviceMessenger == null) {
                try {
                    throw new IllegalAccessException("绑定成功但是 serviceMessenger 是 null");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }


        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    Handler cHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what != 0x00) {
                stringBuilder.append("\n");
                stringBuilder.append( msg.getData().getString("cms"));
                Log.d(TAG, "handleMessage: 我收到了服务端发来的消息");
                messengerMsShow.setText(stringBuilder.toString());
            }else if(msg.what==0){

            }
        }
    };
    Messenger cMessenger = new Messenger(cHandler);

    public void initView() {
        messenger_send_messenger_to_service = findViewById(R.id.messenger_send_messenger_to_service);
        messengerSendMsToService = findViewById(R.id.messenger_send_ms_to_service);
        messengerMsShow = findViewById(R.id.messenger_ms_show);
        messenger_send_messenger_to_service.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message message = Message.obtain();
                message.what = 0x00;
                message.replyTo = cMessenger;
                Bundle bundle=new Bundle();
                message.setData(bundle);
                try {
                    //发送客户端Messenger 到服务端,本意在建立链接
                    serviceMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

        });
        messengerSendMsToService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message message = Message.obtain();
                message.what = 0x02;
                Bundle bundle=new Bundle();
                bundle.putString("ms","我是客户端,我向服务端发送了一条请求");
                message.setData(bundle);
                try {
                    //发送客户端Messenger 到服务端
                    serviceMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp">

    <Button
        android:id="@+id/messenger_send_messenger_to_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="绑定service" />

    <Button
        android:id="@+id/messenger_send_ms_to_service"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="向服务端发送消息"/>
    <TextView
        android:id="@+id/messenger_ms_show"
        android:layout_marginTop="40dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>
</LinearLayout>

 

 资源下载地址:https://download.csdn.net/download/u013179982/12305267

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章