当前位置:   article > 正文

Android中的Messenger的原理及基本用法_android messagelistener用法

android messagelistener用法

这边博客主要记录一下Android中Messenger的基本原理和用法。


简单来讲,Messenger其实就是Binder通信的包装器,是一种基于消息传递的进程间通信工具。

//Messenger实现了Parcelable接口,因此可以跨进程传输
public final class Messenger implements Parcelable {
    ...............
}
  • 1
  • 2
  • 3
  • 4

通常情况下,我们可以在A进程中创建一个Messenger,然后将该Messenger传递给B进程。
于是,B进程就可以通过Messenger与A进程通信了。


Messenger通常与Handler一起使用,我们看看对应的源码:

public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
    ...........
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

跟进一下Handler的getIMessenger函数:

    .............
    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            //返回的是Handler中定义的MessengerImpl
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    //此处MessengerImpl继承自IMessenger.Stub
    //容易看出MessengerImpl将作为Binder通信的接收端
    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

从上述代码可以看出,Messenger实际上作为了一个Binder服务端的wrapper。


当我们在A进程中创建Messenger,然后传递给B进程时,Messenger需要执行Parcelable接口定义的操作,于是:

    //在A进程中将Binder信息写入到Parcel中
    public void writeToParcel(Parcel out, int flags) {
        out.writeStrongBinder(mTarget.asBinder());
    }

    public static final Parcelable.Creator<Messenger> CREATOR
            = new Parcelable.Creator<Messenger>() {
        //在B进程中,重新创建Binder
        public Messenger createFromParcel(Parcel in) {
            IBinder target = in.readStrongBinder();

            //调用Messenger的另一个构造函数
            return target != null ? new Messenger(target) : null;
        }

        public Messenger[] newArray(int size) {
            return new Messenger[size];
        }
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

跟进一下Messenger的另一个构造函数:

public Messenger(IBinder target) {
    //得到的是Binder通信的客户端
    mTarget = IMessenger.Stub.asInterface(target);
}
  • 1
  • 2
  • 3
  • 4

因此,当Messenger从进程A传递到进程B时,它就变为了Binder通信客户端的wrapper。


当在进程B中使用Messenger的接口时:

public void send(Message message) throws RemoteException {
    //mTarget为Binder通信的客户端,将消息发送给服务端的send函数
    //即服务端Handler的MessengerImpl的send函数
    //上文已经附上了对应代码,可以看到对应的消息将递交给Handler处理
    mTarget.send(message);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

以上就是Messenger通信的原理,现在实际测试一下。
我们定义一个简单的demo,包含一个Activity和一个Service,其中Service与Activity处在不同的进程中。

AndroidManifest.xml中的定义如下:

        .....................
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <service
            android:name=".RemoteService"
            android:enabled="true"
            android:exported="true"
            <!--指定服务运行在其它进程-->
            android:process=".remote">
        </service>
        ..............
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Activity的界面很简单,当点击时就会像Service发送消息,Activity代码如下:

public class MainActivity extends AppCompatActivity {
    private Button mButton;

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

        //打印Activity的pid及所在进程名称
        Log.d("ZJTest", "Activity, pid: " + Process.myPid() +
                ", name: " + Util.getProcessName(this));

        //启动服务
        startService();

        //绑定服务
        bindService();

        mButton = (Button) findViewById(R.id.test_button);
        mButton.setEnabled(false);
        //点击按键后,利用Messenger向Service发送消息
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mMessenger != null) {
                    try {
                        Message msg = Message.obtain();
                        msg.what = 1;
                        mMessenger.send(msg);
                    } catch (RemoteException e) {
                        Log.d("ZJTest", e.toString());
                    }
                }
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unBindService();
        stopService();
    }

    private Intent mIntent;
    private void startService() {
        mIntent = new Intent(this, RemoteService.class);
        this.startService(mIntent);
    }

    private ServiceConnection mServiceConnection;
    private void bindService() {
        mServiceConnection = new LocalServiceConnection();
        this.bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
    }

    Messenger mMessenger;
    private class LocalServiceConnection implements android.content.ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定服务后,获得Messenger并激活Button
            mMessenger = new Messenger(service);
            mButton.setEnabled(true);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mButton.setEnabled(false);
        }
    }

    private void stopService() {
        stopService(mIntent);
    }

    private void unBindService() {
        unbindService(mServiceConnection);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

Service对应的代码如下:

public class RemoteService extends Service {
    private Messenger mMessenger;

    @Override
    public void onCreate() {
        super.onCreate();

        //同样打印进程号及名称
        Log.d("ZJTest", "Service, pid: " + Process.myPid()
                + ", name: " + Util.getProcessName(this));

        LocalHandler mHandler = new LocalHandler();

        mMessenger = new Messenger(mHandler);
    }

    private static class  LocalHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            Log.d("ZJTest", "receive msg: " + msg.what);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        //被绑定时,返回Messenger
        return mMessenger.getBinder();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

获取进程名的代码如下:

class Util {
    static String getProcessName(Context context) {
        int pid = Process.myPid();
        ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);

        for (ActivityManager.RunningAppProcessInfo appProcessInfo:
                am.getRunningAppProcesses()) {
            if (appProcessInfo.pid == pid) {
                return appProcessInfo.processName;
            }
        }

        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

上述代码都是比较简单的,现在来看看运行结果:

02-20 21:25:15.760 D/ZJTest  (30460): Activity, pid: 30460, name: stark.a.is.zhang.messengertest
02-20 21:25:15.769 D/ZJTest  (30428): Service, pid: 30428, name: .remote
02-20 21:25:32.111 D/ZJTest  (30428): receive msg: 1
  • 1
  • 2
  • 3

从log可以看出,Activity与Servie运行在不同的进程中,Messenger确实可以在不同进程间传递消息。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/122602
推荐阅读
相关标签
  

闽ICP备14008679号