进程间通信之Messenger

一、概述

Android中谈进程间通信肯定是要提AIDL,而Messenger底层就是运用了AIDL,对AIDL做了简单封装。但是它和AIDL又有些不同,Messenger利用了Handler处理通信,所以它是线程安全的(不支持并发处理);而AIDL不是线程安全的(支持并发处理)。

二、简单入门

这里,写两个apk,一个作为client,一个座位server。
服务端代码:
创建service:

//处理消息
    private static class MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case 1:
                Message message = Message.obtain(null,0);
                String data = msg.getData().getString("msg");
                System.out.println( "msg----------" + data); ;
                Messenger client = msg.replyTo ;
                Bundle bundle = new Bundle();
                bundle.putString("msg", "服务端消息已经收到");
                message.setData(bundle);
                try {
                    client.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                } 
                break;

            default:
                break;
            }
        }
    }

创建一个Handler的继承类

private Messenger messenger = new Messenger(new MyHandler()) ;

通过handler创建一个Messenger对象。

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

在onBind方法中返回IBinder。

<service android:name="com.lw.messengerdemo.MessengerService">
            <intent-filter>
                <action android:name="com.lw.messengerdemo"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

不要忘记在清单文件中配置了。

客户端:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent() ;
        intent.setAction("com.lw.messengerdemo") ;
        intent.setPackage("com.lw.messengerdemo");
        bindService(intent, new ServiceConnection() {

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Toast.makeText(getApplicationContext(), "failed", 1).show();
            }
            //service连接上了
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Toast.makeText(MainActivity.this, "success", 1).show() ;
                server = new Messenger(service);
                //获取消息
                Message message = Message.obtain(null, 1) ;
                Bundle bundle = new Bundle();
                bundle.putString("msg", "hello word ,我是客户端") ;
                //为消息绑定数据
                message.setData(bundle) ;
                message.replyTo = mReply ;
                //发送
                try {
                    //使用信使发送消息
                    server.send(message) ;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, Context.BIND_AUTO_CREATE) ;
    }

绑定服务。绑定成功后,通过服务端返回的IBinder对象封装成一个Messenger,然后通过Messenger发送消息。注意下面这几行代码:

private static  class MessengerHandler  extends  Handler{

        public void handleMessage(Message msg) {
            switch (msg.what) {
            case 0:
                Messenger client = msg.replyTo ;
                String data = msg.getData().getString("msg");
                System.out.println("msg -------" + data );
                break;

            default:
                break;
            }
        };
    } ;

private Messenger mReply = new Messenger(new MessengerHandler()) ;
message.replyTo = mReply ;

这是用来处理服务端接收到信息后返回给客户端的。
运行结果:

06-18 11:47:19.252: I/System.out(11245): msg----------hello word ,我是客户端

06-18 11:47:19.320: I/System.out(11226): msg -------服务端消息已经收到

三、工作原理

首先看服务端的这行代码:

@Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
/**
     * 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();
    }

这里的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();
    }

通过我们传递过来的handler获取一个IMessenger对象。

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

再看看MessengerImpl是什么东东

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

MessengerImpl继承了IMessenger.Stub。到这里应该清楚了,如果我们在写AIDL的时候,在服务端就是继承Stub然后返回的。查看IMessenger的源码

/* //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);
}

只有一个send(in Message msg),方法MessengerImpl继承stub实现了send方法,最后可以看到交给了Handler处理。

Handler.this.sendMessage(msg);

接着,当和服务连接成功后,如下代码:

server = new Messenger(service);

跟进去

/**
     * 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);
    }

这里又是比较熟悉,通过IBinder返回一个AIDL接口对象,接着就可以通过AIDL接口对象调用方法。这里只是分析了客户端调用服务端,可以看出与AIDL类似。

接着服务端调客户端,这里我也不是太懂,看其鸿神博客的。

Android 基于Message的进程间通信 Messenger完全解析推荐看一下
,首先应该注意一个非常重要的

message.replyTo = mReply ;//这个mReply就是Messenger对象

查看源码,看replyTo 是什么东西

/**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;

通过消息携带一个客户端的Messenger到服务端。查看Message源码:

public final class Message implements Parcelable {

可见它是一个可序列化对象,如果还不知道序列化的请看序列化的两种方式。Message的反序列化代码,这里只用看replyTo 参数

 private void readFromParcel(Parcel source) {
        what = source.readInt();
        arg1 = source.readInt();
        arg2 = source.readInt();
        if (source.readInt() != 0) {
            obj = source.readParcelable(getClass().getClassLoader());
        }
        when = source.readLong();
        data = source.readBundle();
        replyTo = Messenger.readMessengerOrNullFromParcel(source);
        sendingUid = source.readInt();
    }

replyTo 又是Messenger.readMessengerOrNullFromParcel(source);赋值,

/**
     * 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;
    }

那么看它是如何write的



    /**
     * 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);
    }

这里的messenger.mTarget.asBinder()其实就是MessengerImpl。首先分析Message是如何创建的?前面提到过,再看一遍

/**
     * 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();
    }

    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);
        }
    }

    public IBinder getBinder() {
        return mTarget.asBinder();
    }

    IMessenger.Stub
    @Override 
    public android.os.IBinder asBinder()
    {
    return this;
    }

由此可以看出messenger.mTarget.asBinder()返回的就是MessengerImpl

源码下载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值