服务(Service)是Android的四大组件之一,它利用底层Binder机制,实现了RPC机制。 一个服务即可以存在于一个独立的进程,也可以依附于已存在的某个进程中。服务可被同一进程中的Activity调用,也可以被位于不同进程中的某个Activity调用。 本文主要探讨怎样编写一个远程服务接口的过程。为演示作用,本文不介绍通过AIDL语言自动生成服务接口代码的过程。
首先,我们定义接口:
public interface IRemoteService extends IInterface { /** * serviceMethod */ public void serviceMethod(int arg0, float arg1, long arg2, boolean arg3, double arg4, String arg5) throws RemoteException; }
接下来的重点就是实现上述定义的服务接口,这里,为了支持同一进程和不同进程的Activity都能够调用该服务接口,我们需要两个接口实现,一个是本地实现,一个是远程实现。在介绍这两个实现代码之前,我们先看下对应的RemoteService类的实现:
public RemoteService extends Service { @Override public void onCreate() { } @Override public void onDestroy() { } @Override public IBinder onBind(Intent intent) { // Select the interface to return. If your service only implements // a single interface, you can just return it here without checking // the Intent. if (IRemoteService.class.getName().equals(intent.getAction())) { return mBinder; } return null; } /** * The IRemoteInterface is defined through IDL */ private final RemoteServiceStub mBinder = new RemoteServiceStub() { public void serviceMethod(int arg0, float arg1, long arg2, boolean arg3, double arg4, String arg5) { //do something here } }; }
首先是本地接口实现类,代码如下:
/** Local-side IPC implementation stub class. */ public abstract class RemoteServiceStub extends Binder implements IRemoteService { private static final String DESCRIPTOR = "com.fyj.test.IRemoteService"; /** Construct the stub at attach it to the interface. */ public RemoteServiceStub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an * com.fyj.test.IRemoteService interface, generating a * proxy if needed. */ public static IRemoteService asInterface(IBinder obj) { if ((obj == null)) { return null; } IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof IRemoteService))) { return ((IRemoteService) iin); } return new RemoteServiceProxy(obj); } public IBinder asBinder() { return this; } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_methodService: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); float _arg1; _arg1 = data.readFloat(); long _arg2; _arg2 = (0!=data.readLong()); boolean _arg3; _arg3 = data.readInt()?true:false; double _arg4; _arg4 = data.readDouble(); String _arg5; _arg5 = data.readString(); this.serviceMethod(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } public void serviceMethod(int arg0, float arg1, long arg2, boolean arg3, double arg4, String arg5) throws RemoteException; static final int TRANSACTION_methodService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); }
/** Local-side IPC implementation stub class. */ public class RemoteServiceProxy implements IRemoteService { private static final String DESCRIPTOR = "com.fyj.test.IRemoteService"; private IBinder mRemote; RemoteServiceProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public String getInterfaceDescriptor() { return DESCRIPTOR; } public void serviceMethod(int arg0, float arg1, long arg2, boolean arg3, double arg4, String arg5) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(anInt); _data.writeFloat(aFloat); _data.writeLong(aLong); _data.writeInt(((aBoolean)?(1):(0))); _data.writeDouble(aDouble); _data.writeString(aString); mRemote.transact(TRANSACTION_methodService, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } static final int TRANSACTION_methodService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); }
在调用bindService的过程中,需要传递一个ServiceConnection对象,该对象将在服务连接成功后,会接收到服务类的对象,以此可以判断当前应该使用本地服务类实现,还是远程服务类实现,关于具体的实现细节,将另外专题分析。 下面给出ServiceConnection对象实现创建的代码:
private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // TODO Auto-generated method stub mService = RemoteServiceStub.asInterface(service); ... } public void onServiceDisconnected(ComponentName className) { // TODO Auto-generated method stub mService = null; ... } };