1. 程式人生 > >使用Messenger進行跨應用(程序)通訊

使用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地址