多進程間通信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

 

 

 

 

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