publicabstractclass
Service
extendsContextWrapper
implementsComponentCallbacks
java.lang.Object
android.content.Context
android.content.ContextWrapper
android.app.Service
ClassOverview
AServiceisanapplicationcomponentrepresentingeitheranapplication'sdesiretoperformalonger-runningoperation
whilenotinteractingwiththeuserortosupplyfunctionalityforotherapplicationstouse.Eachserviceclassmusthaveacorresponding<service>declarationinitspackage'sAndroidManifest.xml.ServicescanbestartedwithContext.startService()andContext.bindService().
Notethatservices,likeotherapplicationobjects,runinthemainthreadoftheirhostingprocess.Thismeansthat,ifyourserviceisgoingtodoanyCPUintensive(suchasMP3playback)orblocking(suchasnetworking)operations,itshouldspawnitsownthreadinwhichtodothatwork.MoreinformationonthiscanbefoundinApplicationFundamentals:ProcessesandThreads.TheIntentServiceclassisavailableasastandardimplementationofServicethathasitsownthreadwhereitschedulesitsworktobedone.
Service主要用来处理运行在后台的耗时操作。每个Service必须在AndroidManifest.xml中进行声明。可以通过Context.startService()andContext.bindService()来启动Service。Service也是运行在主要线程的。所以如果想要做些非常耗CPU(放MP3)或阻塞操作(网络),最好自己新建个线程来做这些工作。IntentService就是一个Intent的标准实现哦。它拥有它自己的线程。
什么是Service呢?
有两个需要强调的概念是:
*AServiceisnotaseparateprocess.
TheServiceobjectitselfdoesnotimplyitisrunninginitsownprocess;
unlessotherwisespecified,itrunsinthesameprocessastheapplicationitispartof.
Service本身并没有运行在一个单独的进程上面。如果没有特殊的规定,它运行在它所在的那个应用程序的进程上面。
*AServiceisnotathread.Itisnotameansitselftodoworkoffofthemainthread(toavoidApplicationNotRespondingerrors).
Service也不是个线程。他本身也运行在主线程中。它本身并不能避免应用程序没有响应的错误
ThusaServiceitselfisactuallyverysimple,providingtwomainfeatures:
然而Service实际上本身是很简单的,它主要有以下两个属性
*Afacilityfortheapplicationtotellthesystemaboutsomethingitwantstobedoinginthebackground
(evenwhentheuserisnotdirectlyinteractingwiththeapplication).ThiscorrespondstocallstoContext.startService(),whichaskthesystemtoscheduleworkfortheservice,toberununtiltheserviceorsomeoneelseexplicitlystopit.
Service只是告诉系统,它是运行在后台。调用Context.startService(),系统就会安排service来运行,直到它自己或别人显式的停止它.*Afacilityforanapplicationtoexposesomeofitsfunctionalitytootherapplications.ThiscorrespondstocallstoContext.bindService(),whichallowsalong standingconnectiontobemadetotheserviceinordertointeractwithit.Service为进程之间通信提供了便利。可以通过调用Context.bindService()来实现。对于本地的通信也提供方便。
对于本地通信也是通过Context.bindService(),只是不用提供AIDL来声明远程接口。当Service被创建时,所有这些系统实际所做的是实例化该组件并调用它的OnCreate()和主线程上的任何其他合适的回调。
Service任何时候最多只有一个实例。多此次调用Context.startService,不会产生多个实例。通常,在Service中新建一个线程。让该线程来做些耗时的工作。Service的本身生命周期:
1,
当调用Context.startService()时,如果Service还没创建就会调用onCreate(),然后调用onStartCommand(Intent,int,int),
如果已经创建,就不会掉用onCreate(),直接调用onStartCommand(Intent,int,int)。
Service创建后直到调用Context.stopService()orstopSelf()才回消亡。 如果使用stopSelf(intstartId)的话,它直到startId的那个Intent被执行完才消亡.这里的startId对应于onStartCommand(Intent,int,int)的第三个参数startId。2,
当Service启动后,它的有三种运行模式。它取决于从onStartCommand()中返回的值。2.1,
如果是START_STICKY,就说明它是显式启动的,也要显式的来停止.即如果它因为内存的原因被系统杀死了的话,系统可以让它重生。
注意它在被杀死时,不会保存已经发送了的Intent.如果重生时,没有未处理的Intent,
那么onStartCommand(Intent,int,int)中的Intent就是null,2.2,
如果是START_NOT_STICKY,当它因为内存的原因被系统杀死的时候,如果没有Intent需要传送。
那么即使内存充足的是时候,它也不会立即被重新创建启动。它要直到Context.startService(Intent),才重新被创建启动。2.3,如果是START_REDELIVER_INTENT,当它因为内存的原因被系统杀死。那么内存充足的是时候,它立即被重新创建启动。
这时它在被杀死钱前传递的那个Intent会再次传递到onStartCommand(Intent,int,int)中,因此其不可能Intent就是null3,
客户也可以使用Context.bindService()来取得和服务的永久性链接.
如果服务没有启动,那么这将创建它(调用onCreate()),
但不会调用onStartCommand().客户将获取IBinder对象,这些对象由服务的onBind(Intent)方法返回,
以便客户能够向服务发出调用.只要链接建立,服务就会一直运行(不管客户是否保留服务的IBinder的引用).
通常IBinder是使用aidl写成的一个复杂接口.
4,Service可以同时以start和绑定连接的方式使用。这时只要有start的没有stop,或至少有一个通过Context.BIND_AUTO_CREATE来绑定的连接没有断开,那么Service就不会调onDestroy()方法,也不会消亡。
Permissions
如果一个服务在manifest中的<service>中声明一个服务的强制全局访问,
那么其它的应用程序必须在对应的<user-permission>元素中做相应权限的声明,以便启动,停止或者绑定该服务.
此外,一个服务可以使用权限来保护一个IPC调用.使用checkCallingPermission(String)方法.
ProcessLifecycle进程生命周期
android系统会试图保持持有服务的进程运行,只要该服务被启动或者有客户连接它.
当内存不足时,持有服务的进程将有较高的优先级
1,如果服务正在运行onCreate(),onStartCommand()或者onDestroy()的代码,那么持有服务的进程将变为前台进程。
它是不会被系统杀死的。
2,当Service被创建后,他所驻留的进程虽然比可见的进程优先级低,但是它比不可见的进程高。
因为大多数进程都是不可见的,所有Service也只会在内存非常低的时候才被系统杀死。
3,如果有客户端绑定到了Service,那么该Service所驻留的优先级就不比该客户端的进程低。
即如果该客户端是可见的话,那么该进程就和可见的线程的优先级一样。
4,一个已启动的服务可以通过调研startForeground(int,Notification)API来将服务放在前台状态,
系统认为它是用户可见的,因此在内存低的时候不会被kill. 当然从理论上来说它也可能在当前应用程序面临巨大内存不足的情况下被杀死,但一般不考虑这种情况。
注意1:通过上面我们知道大部分服务在运行的时候,它有可能被系统Kill掉.这样,系统之后会重启该服务.
如果你实现onStartCommand()来安排异步工作或者在另一个线程中工作, 那么你可能需要使用START_FLAG_REDELIVERY来让系统重新发送一个intent。这样如果你的服务在处理它的时候被Kill掉,Intent不会丢失.
注意2:应用程序进程的优先级是由其包中正在运行的程序组件(service,Activity)中最高者决定的。
例1:start启动方式。并没处理什么实质的工作
Buttonbutton3=(Button)findViewById(R.id.Button03);
OnClickListenerlistener3=newOnClickListener(){
@Override
publicvoidonClick(Viewv){
Intentintent=newIntent(Hello.this,MyService.class);
startService(intent);
}
};
button3.setOnClickListener(listener3);
Buttonbutton4=(Button)findViewById(R.id.Button04);
OnClickListenerlistener4=newOnClickListener(){
@Override
publicvoidonClick(Viewv){
Intentintent=newIntent(Hello.this,MyService.class);
stopService(intent);
}
};
button4.setOnClickListener(listener4);
mainfest.xml文件中
<serviceandroid:name=".MyService"></service>
MyService.java
文件
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.IBinder;
importandroid.util.Log;
publicclass
MyServiceextendsService{
Stringtag="hubin";
@Override
publicvoidonCreate(){
Log.i(tag,"oncreate");
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
Log.i(tag,"Receivedstartid"+startId+":"+intent);
//Wewantthisservicetocontinuerunninguntilitisexplicitly
//stopped,soreturnsticky.
returnSTART_STICKY;
}
@Override
publicvoidonDestroy(){
Log.i(tag,"OnDestory");
}
@Override
publicIBinderonBind(Intentarg0){
//TODOAuto-generatedmethodstub
returnnull;
}
}
例2:start启动方式。已经可以处理工作,但没有通信
publicclass
MyServiceextendsServiceimplementsRunnable{
Stringtag="hubin";
@Override
publicvoidonCreate(){
Log.i(tag,"oncreate");
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
Log.i(tag,"Receivedstartid"+startId+":"+intent);
//Wewantthisservicetocontinuerunninguntilitisexplicitly
//stopped,soreturnsticky.
if(blRun==false)
{
Threadt=newThread(this);
t.start();
}
returnSTART_STICKY;
}
@Override
publicvoidonDestroy(){
blRun=false;
Log.i(tag,"OnDestory");
}
@Override
publicIBinderonBind(Intentarg0){
//TODOAuto-generatedmethodstub
returnnull;
}
booleanblRun=false;
finalstaticintkSleepTime=5;
publicvoidrun()
{
blRun=true;
while(blRun)
{
Log.i(tag,"run"+System.currentTimeMillis());
try{
Thread.sleep(kSleepTime);
}catch(InterruptedExceptione)
{
Log.e(tag,"InterruptedException",e);
}
}
}
}
例3:启动方式。可以处理工作,虽然没有通信,但是已经可以通过Intent来发命令。
Intentintent=newIntent(Hello.this,MyService.class);
Stringvalue="Hello"+System.currentTimeMillis();
intent.putExtra("cmd",value);
startService(intent);
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.IBinder;
importandroid.util.Log;
publicclass
MyServiceextendsServiceimplementsRunnable{
Stringtag="hubin";@OverridepublicvoidonCreate(){Log.i(tag,"oncreate");}@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){Log.i(tag,"Receivedstartid"+startId+":"+intent);//Wewantthisservicetocontinuerunninguntilitisexplicitly//stopped,soreturnsticky.if(blRun==false){Threadt=newThread(this);t.start();}if(intent!=null){Stringcmd=intent.getStringExtra("cmd");if(cmd!=null)
{
addCmd(cmd);
}}returnSTART_STICKY;}@OverridepublicvoidonDestroy(){blRun=false;Log.i(tag,"OnDestory");}@OverridepublicIBinderonBind(Intentarg0){//TODOAuto-generatedmethodstubreturnnull;}booleanblRun=false;finalstaticintkSleepTime=5;finalStringcmdPool[]=newString[10];intcmdStartCursor=-1;intcmdEndCursor=-1;publicvoidrun(){blRun=true;while(blRun){if(cmdStartCursor!=cmdEndCursor){cmdStartCursor=(cmdStartCursor+1)%cmdPool.length;Log.i(tag,"run:"+cmdPool[cmdStartCursor]);}try{Thread.sleep(kSleepTime);}catch(InterruptedExceptione){Log.e(tag,"InterruptedException",e);}}}voidaddCmd(Stringcmd)
{if((cmdEndCursor+1)%cmdPool.length!=cmdStartCursor){cmdEndCursor++;cmdEndCursor=cmdEndCursor%cmdPool.length;cmdPool[cmdEndCursor]=cmd;}}
}
例4:绑定方式。可以处理工作,实现了进程的本地通信
importandroid.app.Activity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.os.IBinder;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.util.Log;
publicclass
HelloextendsActivity{
finalstaticStringtag="hubin";
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
..............................
Buttonbutton4=(Button)findViewById(R.id.Button04);
OnClickListenerlistener4=newOnClickListener(){
@Override
publicvoidonClick(Viewv){
Intentintent=newIntent(Hello.this,MyService.class);
stopService(intent);}};button4.setOnClickListener(listener4);Buttonbutton5=(Button)findViewById(R.id.Button05);OnClickListenerlistener5=newOnClickListener(){@OverridepublicvoidonClick(Viewv){doBindService();}};button5.setOnClickListener(listener5);Buttonbutton6=(Button)findViewById(R.id.Button06);OnClickListenerlistener6=newOnClickListener(){@OverridepublicvoidonClick(Viewv){doUnbindService();}};button6.setOnClickListener(listener6);Buttonbutton7=(Button)findViewById(R.id.Button07);OnClickListenerlistener7=newOnClickListener(){@OverridepublicvoidonClick(Viewv){if(mBoundService==null){Log.i(tag,"theServicehasnotbind!Pleasebindtheservicefirst");return;}Stringcmd="Hello:"+System.currentTimeMillis()%100;mBoundService.addCmd(cmd);}};button7.setOnClickListener(listener7);}privateMyServicemBoundService;privateServiceConnectionmConnection=newServiceConnection(){
publicvoidonServiceConnected(ComponentNameclassName,IBinderservice){
mBoundService=((MyService.LocalBinder)service).getService();
}
publicvoidonServiceDisconnected(ComponentNameclassName){
mBoundService=null;
}
};booleanmIsBound=true;voiddoBindService(){//Establishaconnectionwiththeservice.Weuseanexplicit//classnamebecausewewantaspecificserviceimplementationthat//weknowwillberunninginourownprocess(andthuswon'tbe//supportingcomponentreplacementbyotherapplications).bindService(newIntent(Hello.this,
MyService.class),mConnection,Context.BIND_AUTO_CREATE);mIsBound=true;}voiddoUnbindService(){if(mIsBound){//Detachourexistingconnection.unbindService(mConnection);mIsBound=false;}}@OverrideprotectedvoidonDestroy(){super.onDestroy();doUnbindService();}
}
例4:绑定方式。可以处理工作,实现了两个进程的通信
具体参照《
AIDL和Service实现两进程通信》
分享到:
相关推荐
Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。 此外,组件可以绑定到服务,以与之进行交互,甚至是...
再开始之前我们还是先介绍下service吧:此处用的是IntentService,至于和常规的service有什么区别呢? 有了Service为什么还要有个IntentService呢? 原因如下: 1)Service默认运行在主线程中,IntentService运行在一个...
loud Service V2.2培训材料 Cloud service v2.2版本说明docx Cloud service V2.2教学进度表docX Cloud service V2.2课程表xsX Cloud service V2.2培训材料 Cloud service V2.2实验环境搭建指南.docX Cloud service ...
Wiley.SOA MoSOA Modeling Patterns for Service Oriented Discovery and Analysis Wiley | 2010-01-07 | ISBN: 0470481978 | 480 pages | PDF | 7 MB SOA Modeling Patterns for Service-Oriented Discovery and ...
版本: Version: ... 如果以前安装了 Visual Studio 2008 修补程序或 Visual Studio 2008 SP1 预发行版本,则必须在安装 Visual Studio 2008 SP1 之前运行 Service Pack 准备工具。 如果安装了多个
ServiceMesh(服务网格)概念在社区里头非常火,有人提出2018年是ServiceMesh年,还有人提出ServiceMesh是下一代的微服务架构基础。作为架构师,如果你现在还不了解ServiceMesh的话,是否感觉有点落伍了?那么到底什么...
service now web service guide
C# 开机启动服务(windows service) 本程序用ASP.NET C#开发,不针对系统版本限制。 本源码拿就来可以直接写您想要的服务,无需再改其它的代码,拿来主义是不是很好?例如订单服务。 本服务是100%源码,源码中包含: ...
oracle service_name参数
JAVA程序部署为Windows Service,包含:JavaService-2.0.10(32位).zip与JavaService_2_0_10-amd64(64位).zip
可利用javaService将java程序安装为系统服务
目录 HCIP-Cloud Service Solutions Architect V3.0 HCIP-Cloud Service Solutions Architect V3.0 版本说明 HCIP-Cloud Service Solutions Architect V3.0 实验手册
只需要将service文件替换你的arcgis安装目录下的arcgis10.1\License10.1\bin下的service.txt,将计算机名字改为自己的名字即可。
SharePoint 2013 introduces a new distributed cache service based on Windows Server AppFabric distributed caching. The distributed cache is used in features like authentication, to cache FedAuth ...
Service Worker 是 Chrome 团队提出和力推的一个 WEB API,用于给 web 应用提供高级的可持续的后台处理能力。 service worker 能够操作的缓存是有别于浏览器内部的 memory cache 或者 disk cache。它是独立于当前...
tomcat service.bat配置tomcat成服务。
用于安装arcgis 10.0时破解。将service.txt复制到服务下的bin文件夹,将原有的service.txt覆盖
微博Service mesh大规模实践微博
android,启动service,并且service把值传给Activity显示
install Windows Service 需要大于20个字符,不支持HTML标签。