minSdkVersion="3"/>
Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。
packagecom.easymorse;
importandroid.app.Activity;
importandroid.content.ComponentName;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.util.Log;
publicclassLocalServiceDemoActivityextendsActivity{
privateServiceConnectionserviceConnection=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
countService=(ICountService)service;
Log.v("CountService","onserivceconnected,countis"
+countService.getCount());
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
countService=null;
}
};
privateICountServicecountService;
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.bindService(newIntent("com.easymorse.CountService"),
this.serviceConnection,BIND_AUTO_CREATE);
}
@Override
protectedvoidonDestroy(){
this.unbindService(serviceConnection);
super.onDestroy(); //注意先后
}
}
编写传递基本型数据的远程服务
上面的示例,可以扩展为,让其他应用程序复用该服务。
这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。
这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。
扩展名为aidl而不是java。
可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。
packagecom.easymorse;
interfaceICountService{
intgetCount();
}
编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。
桩对象是远程对象的本地代理。
packagecom.easymorse;
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.IBinder;
importandroid.os.RemoteException;
importandroid.util.Log;
publicclassCountServiceextendsService{
privatebooleanthreadDisable;
privateintcount;
privateICountService.StubserviceBinder=newICountService.Stub(){
@Override
publicintgetCount()throwsRemoteException{
returncount;
}
};
@Override
publicIBinderonBind(Intentintent){
returnserviceBinder;
}
@Override
publicvoidonCreate(){
super.onCreate();
newThread(newRunnable(){
@Override
publicvoidrun(){
while(!
threadDisable){
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
}
count++;
Log.v("CountService","Countis"+count);
}
}
}).start();
}
@Override
publicvoidonDestroy(){
super.onDestroy();
this.threadDisable=true;
Log.v("CountService","ondestroy");
}
}
配置文件AndroidManifest.xml和上面的类似,没有区别。
在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获异常。
privateServiceConnectionserviceConnection=newServiceConnection(){
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
countService=(ICountService)service;
try{
Log.v("CountService","onserivceconnected,countis"
+countService.getCount());
}catch(RemoteExceptione){
thrownewRuntimeException(e);
}
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
countService=null;
}
};
这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。
如果是另外的应用程序使用远程服务,需要做的是复制上面的aidl文件和相应的包构到应用程序中,其他调用等都一样。
编写传递复杂数据类型的远程服务
远程服务往往不只是传递java基本数据类型。
这时需要注意android的一些限制和规定:
1.android支持String和CharSequence
2.如果需要在aidl中使用其他aidl接口类型,需要import,即使是在相同包结构下;
3.android允许传递实现