Android应用:Service开发实例(一)之AIDL和远程调用

来源:互联网 发布:视易服务器 mysql 编辑:程序博客网 时间:2024/05/18 08:02

在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的。因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问的目的。在JavaEE中,采用RMI通过序列化传递对象。在Android中, 则采用AIDL(Android Interface Definition Language:接口描述语言)方式实现。

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC 机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应 的对象。由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员 来说是透明的。

下边通过一个简单的例子来说明两个应用之间怎么使用aidl来通信。

一、服务器端开发
新建一个应用。
1、新建一个AIDL接口文件IMyAidlInterface.aidl
package com.dlq.myservice;interface IMyAidlInterface {    void ServiceTest();}
这个AIDL在编译时会自动生成一个IMyAidlInterface.java文件
/* * This file is auto-generated.  DO NOT MODIFY. * Original file: G:\\Android\\AndroidStudioProjects\\MyService\\app\\src\\main\\aidl\\com\\dlq\\myservice\\IMyAidlInterface.aidl */package com.dlq.myservice;// Declare any non-default types here with import statementspublic interface IMyAidlInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.dlq.myservice.IMyAidlInterface{private static final java.lang.String DESCRIPTOR = "com.dlq.myservice.IMyAidlInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.dlq.myservice.IMyAidlInterface interface, * generating a proxy if needed. */public static com.dlq.myservice.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.dlq.myservice.IMyAidlInterface))) {return ((com.dlq.myservice.IMyAidlInterface)iin);}return new com.dlq.myservice.IMyAidlInterface.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_ServiceTest:{data.enforceInterface(DESCRIPTOR);this.ServiceTest();reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.dlq.myservice.IMyAidlInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public void ServiceTest() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_ServiceTest, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_ServiceTest = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public void ServiceTest() throws android.os.RemoteException;}

2、新建一个Service
package com.dlq.myservice;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MyService extends Service {    private static final String TAG = "MyService";    private MyServiceImpl mService;    public MyService() {        Log.d(TAG, "MyService");    }    @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "MyService onCreate");        //在onCreate中实例化一个service        mService = new MyServiceImpl();    }    @Override    public void onStart(Intent intent, int startId) {        super.onStart(intent, startId);        Log.d(TAG, "MyService onStart");    }    @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "MyService onBind");        //在onBind中返回这个service的实例        return mService;    }    //实现aidl文件生成的接口(IMyAidlInterface),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。    private class MyServiceImpl extends IMyAidlInterface.Stub    {        @Override        public void ServiceTest() throws RemoteException {            Log.d(TAG, "MyService ServiceTest");        }    }}
3.在AndroidManifest.xml中添加服务
        <service            android:name=".MyService"            android:enabled="true"            android:exported="true" >        </service>

二、客户端开发
新建另一个应用。
1、新建一个IMyAidlInterface.aidl文件,所在的包名必须和服务器端完全一致
2、在AndroidManifest.xml中添加服务
        <service            android:name="com.dlq.myservice.IMyAidlInterface"            android:enabled="true"            android:exported="true" >        </service>
3、在Activity中的按钮中添加代码,通过bindservice启动服务
Intent intent = new Intent();//这里通过包名和类名启动服务,也可以通过Action来启动intent.setClassName("com.dlq.myservice","com.dlq.myservice.MyService");//android5.0以后必须显示启动服务,intent中需要添加包名intent.setPackage(getPackageName());bindService(intent, con, BIND_AUTO_CREATE);
4、客户端绑定service时在ServiceConnection.onServiceConnected获取onBind返回的IBinder 对象
    private IMyAidlInterface mService;    ServiceConnection con = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mService = IMyAidlInterface.Stub.asInterface(service);            Log.d(TAG, "MyClient mService="+mService);        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };
5、在另一个按钮中调用Service中实现的接口
try {    mService.ServiceTest();} catch (RemoteException e) {    e.printStackTrace();}
6、使用unbindService解除绑定
this.unbindService(con);

三、运行效果

绑定服务
08-14 20:20:25.222    6831-6831/com.dlq.myservice D/MyService﹕ MyService08-14 20:20:25.222    6831-6831/com.dlq.myservice D/MyService﹕ MyService onCreate08-14 20:20:25.223    6831-6831/com.dlq.myservice D/MyService﹕ MyService onBind

调用服务接口
08-14 20:20:28.662    6831-6847/com.dlq.myservice D/MyService﹕ MyService ServiceTest




0 0
原创粉丝点击