1. 程式人生 > >Android跨進程通信Messenger

Android跨進程通信Messenger

stat protected sco urn color 服務端 llb fin server

一.概述

技術分享圖片

我們可以在客戶端發送一個Message給服務端,在服務端的handler中會接收到客戶端的消息,然後進行對應的處理,處理完成後,再將結果等數據封裝成Message,發送給客戶端,客戶端的handler中會接收到處理的結果。

有這麽幾個特點:

  • 基於Message,相信大家都很熟悉

  • 支持回調的方式,也就是服務端處理完成長任務可以和客戶端交互

  • 不需要編寫aidl文件

此外,還支持,記錄客戶端對象的Messenger,然後可以實現一對多的通信;甚至作為一個轉接處,任意兩個進程都能通過服務端進行通信,這個後面再說。

二.應用

package com.imooc.messenger_server;

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

public class MessengerService extends Service { private static final int MSG_SUM = 0x110; //最好換成HandlerThread的形式 private Messenger mMessenger = new Messenger(new Handler() { @Override public void handleMessage(Message msgfromClient) { Message msgToClient = Message.obtain(msgfromClient);//
返回給客戶端的消息 switch (msgfromClient.what) { //msg 客戶端傳來的消息 case MSG_SUM: msgToClient.what = MSG_SUM; try { //模擬耗時 Thread.sleep(2000); msgToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2; msgfromClient.replyTo.send(msgToClient); }
catch (InterruptedException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } break; } super.handleMessage(msgfromClient); } }); @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } }

服務端就一個Service,可以看到代碼相當的簡單,只需要去聲明一個Messenger對象,然後onBind方法返回mMessenger.getBinder();

然後坐等客戶端將消息發送到handleMessage想法,根據message.what去判斷進行什麽操作,然後做對應的操作,最終將結果通過 msgfromClient.replyTo.send(msgToClient);返回。

可以看到我們這裏主要是取出客戶端傳來的兩個數字,然後求和返回,這裏我有意添加了sleep(2000)模擬耗時,註意在實際使用過程中,可以換成在獨立開辟的線程中完成耗時操作,比如和HandlerThread結合使用。

註冊文件

<service
            android:name=".MessengerService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.zhy.aidl.calc"></action>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

(二)客戶端

Activity

package com.imooc.messenger_client;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
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.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final int MSG_SUM = 0x110;

    private Button mBtnAdd;
    private LinearLayout mLyContainer;
    //顯示連接狀態
    private TextView mTvState;

    private Messenger mService;
    private boolean isConn;


    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msgFromServer)  {
            switch (msgFromServer.what)  {
                case MSG_SUM:
                    TextView tv = (TextView) mLyContainer.findViewById(msgFromServer.arg1);
                    tv.setText(tv.getText() + "=>" + msgFromServer.arg2);
                    break;
            }
            super.handleMessage(msgFromServer);
        }
    });


    private ServiceConnection mConn = new ServiceConnection()  {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);
            isConn = true;
            mTvState.setText("connected!");
        }

        @Override
        public void onServiceDisconnected(ComponentName name)  {
            mService = null;
            isConn = false;
            mTvState.setText("disconnected!");
        }
    };

    private int mA;

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

        //開始綁定服務
        bindServiceInvoked();

        mTvState = (TextView) findViewById(R.id.id_tv_callback);
        mBtnAdd = (Button) findViewById(R.id.id_btn_add);
        mLyContainer = (LinearLayout) findViewById(R.id.id_ll_container);

        mBtnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)  {
                try  {
                    int a = mA++;
                    int b = (int) (Math.random() * 100);

                    //創建一個tv,添加到LinearLayout中
                    TextView tv = new TextView(MainActivity.this);
                    tv.setText(a + " + " + b + " = caculating ...");
                    tv.setId(a);
                    mLyContainer.addView(tv);

                    Message msgFromClient = Message.obtain(null, MSG_SUM, a, b);
                    msgFromClient.replyTo = mMessenger;
                    if (isConn)  {
                        //往服務端發送消息
                        mService.send(msgFromClient);
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

    }

    private void bindServiceInvoked()  {
        Intent intent = new Intent();
        intent.setAction("com.zhy.aidl.calc");
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
        Log.e(TAG, "bindService invoked !");
    }

    @Override
    protected void onDestroy()  {
        super.onDestroy();
        unbindService(mConn);
    }
}

代碼也不復雜,首先bindService,然後在onServiceConnected中拿到回調的service(IBinder)對象,通過service對象去構造一個mService =new Messenger(service);然後就可以使用mService.send(msg)給服務端了。

Android跨進程通信Messenger