Android 进程间通信:Messenger

1.概述

项目中常用到的进程间通信更多是用AIDL,在前阵子复习的时候才了解还有 Messenger 这种方法。既然要学习就记录下,以后要用的时候才能快速的掌握。

Messenger 是一种轻量级的IPC方案,它的底层实现是AIDL,可以在不同进程中传递 Message 对象,它一次只处理一个请求,在服务端不需要考虑线程同步的问题,服务端不存在并发执行的情况。

2. Messenger的构造方法

Public constructors

Messenger(Handler target)

Create a new Messenger pointing to the given Handler.

Messenger(IBinder target)

Create a Messenger from a raw IBinder, which had previously been retrieved with getBinder().

3. Messenger 使用 

3.1 客户端步骤:

3.1.1 创建一个handler对象,并实现 handleMessage() 方法,用户接收客户端的消息。

3.1.2 创建Messenger ,封装handler。

3.1.3 用Messenger的 getBinder() 方法获取一个IBinder对象,通过 onBind 返回给客户端。

服务端的Service:

package cn.zzw.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;
import android.util.Log;

public class MessengerService extends Service {

    private static final String TAG = "MessengerService";
    private MessengerHandler mHandler = new MessengerHandler();
    private Messenger mMessenger = new Messenger(mHandler);
    private static final int MSG_SUM = 10086;

    private class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            if(msg.what==MSG_SUM)
            {
                Log.e(TAG,"handleMessage");
                try {
                    int arg1 = msg.arg1;
                    int arg2=msg.arg2;
                    Message msgToClient=Message.obtain(msg);
                    msgToClient.arg1=arg1+arg2;
                    msg.replyTo.send(msgToClient);
                } catch (RemoteException e) {

                }
            }

        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
}

3.2 客户端步骤:

3.2.1 在 Activity 中绑定服务。

3.2.2 创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化

3.2.3 使用Messenger向服务端发送消息

客户端主要代码:

package cn.zzw.messenger.client;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
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.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MessengerClient";
    private TextView mTv;
    private Messenger mService;
    private static final int MSG_SUM = 10086;
    private MessengerHandler mHandler = new MessengerHandler();
    private Messenger mMessenger = new Messenger(mHandler);

    private class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {

            if(msg.what==MSG_SUM)
            {
                Log.e(TAG,"handleMessage");
                int arg1 = msg.arg1;
                Log.e(TAG,"handleMessage:"+arg1);
                Toast.makeText(MainActivity.this,"The Result is "+arg1,Toast.LENGTH_SHORT).show();
            }

        }
    }
    private ServiceConnection conn=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //获取服务端关联的Messenger对象
            mService = new Messenger(iBinder);
            Log.e(TAG,"onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e(TAG,"onServiceDisconnected");
            mService=null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindToServserService();
        mTv = findViewById(R.id.mTv);
        findViewById(R.id.mBtn_cal).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Message msg = Message.obtain(null, MSG_SUM, 10, 500);
                msg.replyTo = mMessenger;
                if(null!=mService)
                {
                    //往服务端发送消息
                    try {
                        Log.e(TAG,"mService.send");
                        mService.send(msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /*
    * 绑定服务端的Service
    */
    private void bindToServserService() {
        Intent intent=new Intent();
        intent.setPackage("cn.zzw.messenger.server");
        intent.setAction("CN.ZZW.MESSENGER.SERVER");
        bindService(intent,conn,BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
        mHandler.removeCallbacksAndMessages(null);
    }
}

4. 运行结果

client端的log:

E/MessengerClient: mService.send
E/MessengerClient: mService.send
    handleMessage
    handleMessage:510
E/MessengerClient: handleMessage
    handleMessage:510

Server端的log:

E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage

 

5.原理

先看下 Messenger 的源码,代码行数非常少:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/Messenger.java

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

/**
 * Reference to a Handler, which others can use to send messages to it.
 * This allows for the implementation of message-based communication across
 * processes, by creating a Messenger pointing to a Handler in one process,
 * and handing that Messenger to another process.
 *
 * <p>Note: the implementation underneath is just a simple wrapper around
 * a {@link Binder} that is used to perform the communication.  This means
 * semantically you should treat it as such: this class does not impact process
 * lifecycle management (you must be using some higher-level component to tell
 * the system that your process needs to continue running), the connection will
 * break if your process goes away for any reason, etc.</p>
 */
public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

    /**
     * Create a new Messenger pointing to the given Handler.  Any Message
     * objects sent through this Messenger will appear in the Handler as if
     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
     * been called directly.
     * 
     * @param target The Handler that will receive sent messages.
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
    
    /**
     * Send a Message to this Messenger's Handler.
     * 
     * @param message The Message to send.  Usually retrieved through
     * {@link Message#obtain() Message.obtain()}.
     * 
     * @throws RemoteException Throws DeadObjectException if the target
     * Handler no longer exists.
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }
    
    /**
     * Retrieve the IBinder that this Messenger is using to communicate with
     * its associated Handler.
     * 
     * @return Returns the IBinder backing this Messenger.
     */
    public IBinder getBinder() {
        return mTarget.asBinder();
    }
    
    /**
     * Comparison operator on two Messenger objects, such that true
     * is returned then they both point to the same Handler.
     */
    public boolean equals(Object otherObj) {
        if (otherObj == null) {
            return false;
        }
        try {
            return mTarget.asBinder().equals(((Messenger)otherObj)
                    .mTarget.asBinder());
        } catch (ClassCastException e) {
        }
        return false;
    }

    public int hashCode() {
        return mTarget.asBinder().hashCode();
    }
    
    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeStrongBinder(mTarget.asBinder());
    }

    public static final Parcelable.Creator<Messenger> CREATOR
            = new Parcelable.Creator<Messenger>() {
        public Messenger createFromParcel(Parcel in) {
            IBinder target = in.readStrongBinder();
            return target != null ? new Messenger(target) : null;
        }

        public Messenger[] newArray(int size) {
            return new Messenger[size];
        }
    };

    /**
     * Convenience function for writing either a Messenger or null pointer to
     * a Parcel.  You must use this with {@link #readMessengerOrNullFromParcel}
     * for later reading it.
     * 
     * @param messenger The Messenger to write, or null.
     * @param out Where to write the Messenger.
     */
    public static void writeMessengerOrNullToParcel(Messenger messenger,
            Parcel out) {
        out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
                : null);
    }
    
    /**
     * Convenience function for reading either a Messenger or null pointer from
     * a Parcel.  You must have previously written the Messenger with
     * {@link #writeMessengerOrNullToParcel}.
     * 
     * @param in The Parcel containing the written Messenger.
     * 
     * @return Returns the Messenger read from the Parcel, or null if null had
     * been written.
     */
    public static Messenger readMessengerOrNullFromParcel(Parcel in) {
        IBinder b = in.readStrongBinder();
        return b != null ? new Messenger(b) : null;
    }
    
    /**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
}

这时候我们在回头看两个构造方法:

 1. public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }


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

 两个构造方法内部都是初始化对象 mTarget:

private final IMessenger mTarget;

再看看 IMessenger,是一个AIDL文件:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/IMessenger.aidl

/* //device/java/android/android/app/IActivityPendingResult.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

在看看Handler 中的部分代码:

    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

从以上代码,可以看出Messenger又跟Binder联系起来了。 最终还是AIDL文件来完成的,只不过Messenger进行了深度的封装AIDL,使用起来更简单。

最后,附上文中的示例代码:https://download.csdn.net/download/zzw0221/11260381

 

参考:

https://blog.csdn.net/hzw2017/article/details/81090319

https://www.jianshu.com/p/48e212d1fde4

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值