Android IPC 之 Service 和 Messenger

fzb12321 7年前
   <p>IPC机制是Android的重要组成部分,本文介绍其中的Service和Messenger。结合模拟的支付调用作为例子,翔实明了,简直不能再良心。</p>    <p>IPC(进程间通信)</p>    <p>Interprocess Communication</p>    <h2>Service</h2>    <p>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.</p>    <p>可以看到主要有两点是比较有特点的:不可见并且和用户长时间交互、为其他应用程序提供服务。</p>    <p>Service可以脱离Activity的生命周期独立存在。不过,有一点看上去Service要比Thread“弱”一些:Service一般是不会在新的线程中运行,如果里面进行了耗时操作的话,还是需要新开线程的。</p>    <p>Service主要分为应用程序内部使用的Local Service 和 进行IPC的Remote Messenger Service(含AIDL)。</p>    <h3>作用</h3>    <ul>     <li> <p>A facility for the application to tell the system <em>about</em> something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to Context.startService() , which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it.</p> <p>应用程序告诉操作系统要在后台处理些事情。</p> </li>     <li> <p>A facility for an application to expose some of its functionality to other applications. This corresponds to calls to Context.bindService() , which allows a long-standing connection to be made to the service in order to interact with it.</p> <p>向其他应用程序暴露自己的一些功能,即跨进程通信。</p> </li>    </ul>    <h3>Service的启动</h3>    <pre>  <code class="language-java">bindService(Intent service, ServiceConnection conn, int flags);</code></pre>    <ul>     <li> <p>service,要绑定的那个Service</p> </li>     <li> <p>coon,这个接口有两个方法,对应service的bind和unbind两个节点。bindService是异步的,onServiceConnected() 作为绑定成功的回调。</p> </li>     <li> <p>flag,设置绑定的模式,如BIND_AUTO_CREATE</p> <p>bindService() 会立即返回空值,Service onBinder() 返回Binder时回调ServiceConnection的 onServiceConnected() 方法,并将该Binder作为参数传入。</p> </li>    </ul>    <pre>  <code class="language-java">startService(Intent service)</code></pre>    <p>使用 bindService() 启动Service,在Service失去所有绑定后将执行 onDestroy() 。</p>    <p>只要使用了 startService() 方法(执行onCreate的调用或者在bind之后的调用),Service不会在Activity退出后stop。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a72c6aa4be9d1b59c47d500085dd8847.jpg"></p>    <p>Lifecycle of Service</p>    <h3>IBinder/Binder</h3>    <p>远程对象的基本接口,为进行高性能的进程内/间调用而设计的轻量级远程调用机制的核心部分。这个接口描述了与远程对象进行交互的抽象协议。一般使用的时候从Binder继承,不要直接implement这个接口。</p>    <pre>  <code class="language-java">IBinder onBind();</code></pre>    <p>真正的通信部分由Binder完成。API文档中有更具体的描述</p>    <p>一般来说,对于一个仅仅在应用程序内部使用的Service我们可以拓展Binder,添加getService()这个方法,来达到暴露Service内部功能的目的。但是对于进程间的调用来说这样就很难行得通了(本地没有对应的class文件,不知道Service里面到底添加了哪些方法),所以,自上而下,来看Messenger。</p>    <h2>Messenger</h2>    <p>这个类的注释文档中写道:</p>    <p>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>    <p>Note: the implementation underneath is just a simple wrapper around a {@link Binder} that is used to perform the communication.</p>    <p>引用,指向一个Handler。可以被用来发送消息(充当信使/邮差的功能)。通过在一个进程创造一个 <strong>指向Handler</strong> 的Messenger <strong>并且把这个Messenger传递到另一个进程</strong> ,来允许基于Message的进程间通信。</p>    <p>注意:这个类的底层是对Binder的一个简单封装,Binder是用来执行通信的。(这个类的结构很简单,里面封装了一些Binder的行为)</p>    <p>虽然把这些名称翻译成中文挺奇怪的,但是找到这些类在现实生活中的映射对于更好的理解有很大帮助。Messenger,译作“信使”,应该是古代负责传递消息的使节或衙役之类的人物。在IPC机制中起到的作用就应该是传递信息,比如Service持有一个Messenger,通过这个Messenger发送消息。</p>    <h3>Constructor</h3>    <pre>  <code class="language-java">new Messenger(IBinder/Handler target); //IBinder-Client / Handler-Service</code></pre>    <p>构造方法可以接收两种参数,也分别对应了两种情形:</p>    <ul>     <li> <p>IBinder</p> <p>在绑定Activity的时候, bindService() 要求一个参数ServiceConnection,而绑定成功的回调结果就是一个Binder(由Service的onBind()返回)。</p> <p>这个构造方法一般是用在请求绑定的一端,构造出来的 Messenger 向Service发送 Message 。</p> </li>     <li> <p>Handler</p> <p>Handler作为Android里的跨线程机制的重要组成部分,和Message一直有着密不可分的关系。它的作用就是handle一些东西(Message),而在Service的使用中,一般是由请求端向Service端发出一个请求(信息包含在Message里)。这也就意味着,在引入Messenger的情况下,Service中要包含一个Handler用来处理发过来的请求。</p> <p>这个构造方法一般用在Service端,将Handler和Messenger链接起来。</p> </li>    </ul>    <p>以上两个构造方法完成了Messenger的传递。</p>    <h3>具体过程</h3>    <p>Messenger的主要作用过程如下:</p>    <ol>     <li> <p>Messenger在Service中以Handler以参数创建</p> <pre>  <code class="language-java">Messenger mMessenger = new Messenger(new PaymentHandler()); //Simple Sample</code></pre> </li>     <li> <p>Service被绑定后,发起绑定的一方用Binder为参数创建。</p> <p>Service中返回Messenger的Binder:</p> <pre>  <code class="language-java">@Override      public IBinder onBind(Intent intent) {          Log.i(TAG, "onBind");          return mMessenger.getBinder();      }</code></pre> <p>Activity(eg.)中获取并实例化:</p> <pre>  <code class="language-java">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) {              ......          }      };</code></pre> </li>     <li> <p>进行通信:</p> <pre>  <code class="language-java">Message msg = Message.obtain();  //fill your info into msg  messenger.send(msg);</code></pre> </li>    </ol>    <h3>实现双向的消息发送</h3>    <p>在ServiceConnection的 onServiceConnected() 里面发送一个Message,具体过程如下:</p>    <ul>     <li>new 一个Handler,负责处理Service发过来的消息</li>     <li>用这个Handler创建一个Messenger</li>     <li>发送一个Message,replyTo设置为刚才创建的Messenger</li>    </ul>    <p>一个实例:</p>    <p>​ 模拟一个支付调用,简单得有些简陋。</p>    <p>​ 一侧:</p>    <pre>  <code class="language-java">@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();              }</code></pre>    <p>​ 另一侧:</p>    <pre>  <code class="language-java">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();              }          }</code></pre>    <p>打印出来的Log如下:</p>    <pre>  <code class="language-java">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!</code></pre>    <p>Happy Coding :)</p>    <p>via 锅炉工</p>    <p>ref:</p>    <p>Android Developer :: <a href="/misc/goto?guid=4959715941465275336" rel="nofollow,noindex">Service</a></p>    <p> </p>    <p>来自:http://www.jianshu.com/p/46bd9cb29c90</p>    <p> </p>