Android开发

Android IPC之 Service和Messenger

2017-03-16  本文已影响0人  锅炉工

IPC机制是Android的重要组成部分,本文介绍其中的Service和Messenger。结合模拟的支付调用作为例子,翔实明了,简直不能再良心。

IPC(进程间通信)

Interprocess Communication

Service

A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.

可以看到主要有两点是比较有特点的:不可见并且和用户长时间交互、为其他应用程序提供服务。

Service可以脱离Activity的生命周期独立存在。不过,有一点看上去Service要比Thread“弱”一些:Service一般是不会在新的线程中运行,如果里面进行了耗时操作的话,还是需要新开线程的。

Service主要分为应用程序内部使用的Local Service 和 进行IPC的Remote Messenger Service(含AIDL)。

作用

Service的启动

bindService(Intent service, ServiceConnection conn, int flags);
startService(Intent service)

使用 bindService()启动Service,在Service失去所有绑定后将执行onDestroy()

只要使用了startService()方法(执行onCreate的调用或者在bind之后的调用),Service不会在Activity退出后stop。

Lifecycle of Service

IBinder/Binder

远程对象的基本接口,为进行高性能的进程内/间调用而设计的轻量级远程调用机制的核心部分。这个接口描述了与远程对象进行交互的抽象协议。一般使用的时候从Binder继承,不要直接implement这个接口。

IBinder onBind();

真正的通信部分由Binder完成。API文档中有更具体的描述

一般来说,对于一个仅仅在应用程序内部使用的Service我们可以拓展Binder,添加getService()这个方法,来达到暴露Service内部功能的目的。但是对于进程间的调用来说这样就很难行得通了(本地没有对应的class文件,不知道Service里面到底添加了哪些方法),所以,自上而下,来看Messenger。

Messenger

这个类的注释文档中写道:

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.

Note: the implementation underneath is just a simple wrapper around a {@link Binder} that is used to perform the communication.

引用,指向一个Handler。可以被用来发送消息(充当信使/邮差的功能)。通过在一个进程创造一个指向Handler的Messenger并且把这个Messenger传递到另一个进程,来允许基于Message的进程间通信。

注意:这个类的底层是对Binder的一个简单封装,Binder是用来执行通信的。(这个类的结构很简单,里面封装了一些Binder的行为)

虽然把这些名称翻译成中文挺奇怪的,但是找到这些类在现实生活中的映射对于更好的理解有很大帮助。Messenger,译作“信使”,应该是古代负责传递消息的使节或衙役之类的人物。在IPC机制中起到的作用就应该是传递信息,比如Service持有一个Messenger,通过这个Messenger发送消息。

Constructor

new Messenger(IBinder/Handler target); //IBinder-Client / Handler-Service

构造方法可以接收两种参数,也分别对应了两种情形:

以上两个构造方法完成了Messenger的传递。


具体过程

Messenger的主要作用过程如下:

  1. Messenger在Service中以Handler以参数创建

    Messenger mMessenger = new Messenger(new PaymentHandler()); //Simple Sample
    
  2. Service被绑定后,发起绑定的一方用Binder为参数创建。

    Service中返回Messenger的Binder:

    @Override
        public IBinder onBind(Intent intent) {
            Log.i(TAG, "onBind");
            return mMessenger.getBinder();
        }
    

    Activity(eg.)中获取并实例化:

    ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //来自Service的Messenger
                Messenger messenger = new Messenger(service);
                ......
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                ......
            }
        };
    
  3. 进行通信:

    Message msg = Message.obtain();
    //fill your info into msg
    messenger.send(msg);
    

实现双向的消息发送

在ServiceConnection的onServiceConnected()里面发送一个Message,具体过程如下:

一个实例:

​ 模拟一个支付调用,简单得有些简陋。

​ 一侧:

@SuppressLint("HandlerLeak")
            Handler responseHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                  //打印支付结果
                    Log.i(TAG, "handleMessage: Response from Service");
                    Log.i(TAG, "handleMessage: " + msg.obj);
                }
            };
            msg.replyTo = new Messenger(responseHandler);

//发起支付请求
            msg.obj = "I request to pay $233.33.";
            try {
                messenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

​ 另一侧:

public void handleMessage(Message msg) {
  //打印支付的消息内容
            Log.i(TAG, "handleMessage: " + msg.obj);
            try {
              //模拟支付成功的回调
                Message reply = Message.obtain();
                reply.obj = "Payment Success!";
                msg.replyTo.send(reply);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

打印出来的Log如下:

I/IPC:LocalService: onCreate
I/IPC:LocalService: Received start id 1: Intent { cmp=com.boileryao.ipc/.LocalService }
I/IPC:LocalService: onBind
I/IPC:LocalService: handleMessage: I request to pay $233.33.
I/ContentValues: handleMessage: Response from Service
I/ContentValues: handleMessage: Payment Success!

Happy Coding :)

via 锅炉工

ref:

Android Developer :: Service

上一篇 下一篇

猜你喜欢

热点阅读