在第一节  ​​Android使用binder访问service的方式(一)​​中我们介绍了使用Messenger 进行IPC通信,实现了同一个应用程序中的两个进程之间的通信,这一节讨论如何实现不同应用程序间的通信。

首先我们修改一下上一节的代码,使用Messenger实现不同应用程序间的通信,跟第一节中的service相比,这节我们介绍的service是在另外一个程序中,这一点很关键。在上一节中,我们可以通过service的类名来绑定service,在这一节中我们是不知道远程service的类名的,怎么才能绑定到我们想要的service呢?使用隐试调用即可,我们不指定service的类名,而是指定action和category,然后通过隐试调用去找到远程的service。

客户端访问service代码:



1. new
2. service.setAction(Intent.ACTION_MAIN);
3. service.addCategory(Intent.CATEGORY_DEFAULT);
4. this.bindService(service, mSc, Context.BIND_AUTO_CREATE);



server端的工程需要在AndroidManifest.xml中的修改:




1. <application android:icon="@drawable/ic_launcher">  
2. ".RemoteService">
3. <intent-filter>
4. "android.intent.action.MAIN"
5. "android.intent.category.DEFAULT"
6. </intent-filter>
7. </service>
8. </application>



例子项目在这里 ​​IPCbetween2appbyMessenger.rar​


Messenger通信有一个缺点,Messenger 的处理函数是单线程的,如果你想增加对多线程的支持请使用AIDL,aidl生成的接口是可以被多线程访问的,所以你在编码的时候就要考虑到多线程访问造成的安全隐患。


aidl 是​​Android​​为简化IPC而提供的接口描述语言文件,形式上它只是个​​Java​​接口的定义,其中定义了服务端要暴露给客户端的方法列表,如下定义:




    1. // IRemoteService.aidl
    2. package
    3. // Declare any non-default types here with import statements
    4.
    5. /** Example service interface */
    6. interface
    7. /** Request the process ID of this service, to do evil things with it. */
    8. int
    9.
    10. /** Demonstrates some basic types that you can use as parameters
    11. * and return values in AIDL.
    12. */
    13. void basicTypes(int anInt, long aLong, boolean aBoolean, float
    14. double
    15. }



    这个aidl就定义了两个方法。aidl的更新必须是向后兼容的,以保证使用它的客户端可以正常使用服务。

    将aidl放在src下的某个包里面,clean一下代码,eclipse会自动编译aidl成java类到R文件夹下,客户端就是使用这个java类来与服务端通信。

    服务端同样需要放置aidl到对应的包里面,要与客户端完全一致。


    在服务端:

    实例化 生成的java类的内部类stub,并实现aidl定义的两个方法。




      1. IRemoteService.Stub mBinder = new
      2.
      3. @Override
      4. public int getPid() throws
      5. return 234;
      6. }
      7.
      8. @Override
      9. public void basicTypes(int anInt, long aLong, boolean aBoolean, float
      10. double aDouble, String aString) throws
      11. // TODO Auto-generated method stub
      12. }
      13.
      14. };



      然后将此类从onBind方法中返回给客户端。


      在客户端:

      在onServiceConnected回调方法中获得IBinder对象,通过aidl生成的asInterface方法将其转换成aidl生成的最外部那个类。

      直接调用aidl生成的最外部类就可以调用远程接口了。



      1. mService = IRemoteService.Stub.asInterface(service);  
      2. try
      3. this,"remote service pid is:"+mService.getPid(), Toast.LENGTH_LONG).show();
      4. catch
      5. // TODO Auto-generated catch block
      6. e.printStackTrace();
      7. }


      此部分的演示代码 ​​CommunicatThroughAidl.zip​