Android IPC 通信 (二)

来源:互联网 发布:数据流程图的符号包括 编辑:程序博客网 时间:2024/05/22 10:42

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

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

客户端访问service代码:

Intent service = new Intent();        service.setAction(Intent.ACTION_MAIN);        service.addCategory(Intent.CATEGORY_DEFAULT);        this.bindService(service, mSc, Context.BIND_AUTO_CREATE);

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

<application android:icon="@drawable/ic_launcher">        <service android:name=".RemoteService">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </service> </application>


例子项目在这里 IPCbetween2appbyMessenger.rar


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


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

// IRemoteService.aidlpackage com.ckt.wangxin.remoteservice;// Declare any non-default types here with import statements/** Example service interface */interface IRemoteService {    /** Request the process ID of this service, to do evil things with it. */    int getPid();    /** Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,            double aDouble, String aString);}

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

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

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


在服务端:

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

IRemoteService.Stub mBinder = new IRemoteService.Stub(){        @Override        public int getPid() throws RemoteException {            return 234;        }        @Override        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,                double aDouble, String aString) throws RemoteException {            // TODO Auto-generated method stub        }            };

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


在客户端:

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

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


 mService = IRemoteService.Stub.asInterface(service);                try {                    Toast.makeText(RemoteServiceTestActivity.this,"remote service pid is:"+mService.getPid(), Toast.LENGTH_LONG).show();                } catch (RemoteException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }


此部分的演示代码 CommunicatThroughAidl.zip


原创粉丝点击