编写android服务


服务(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;
			
}

需要说明的是,由于受Binder机制的约束,除基本数据类型外,对于自定义的数据类型,必须实现Parceable接口,才能作为服务方法的参数。本文将不考虑自定义类型作为参数传递的情况。

接下来的重点就是实现上述定义的服务接口,这里,为了支持同一进程和不同进程的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
			}
		};
}

在Android App开发中,定义自己的服务需要从Service类中派生,启动一个Service可以通过startService,也可以通过bindService, 对于通过bindService调用一个服务接口的方式,同时需要实现onBind()方法,它返回的IBinder对应就是我们下面将要介绍的服务实现类。

首先是本地接口实现类,代码如下:

/** 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);
}

它实现为一个抽象类,将接口的具体实现延迟到RemoteService中去实现。在本类 中,主要实现了onTransact()方法,它将处理客户的调用请求。asInterface()接口将自动判断当前是本地调用还是远程调用,如果是远程调用,将使用 RemoteServiceProxy类的实例的接口调用服务,它的实现代码如下:

/** 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;
			...
		}

	};





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值