【移动应用开发技术】Android-Service组件_第1页
【移动应用开发技术】Android-Service组件_第2页
【移动应用开发技术】Android-Service组件_第3页
【移动应用开发技术】Android-Service组件_第4页
【移动应用开发技术】Android-Service组件_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android-Service组件

Service是一个android的四大组件之一,它没有UI界面,可以在后台执行长时间的操作。其他的组件可以start一个Service,service启动以后会在后台持续运行,不管用户是否切换到了其他的应用程序。此外,其他的组件还可以绑定到service上,并和service做交互,甚至还可以执行跨进程的操作(IPC)。比如说,Service可以在后台处理网络请求、播放音乐,执行文件i/o或者跟contentprovider交互。有两种形式的service:Started当其他的组件通过调用startService()启动的service是“Started”。一旦启动以后,service就在后台无限的运行下去,就算是启动他的组件已经被销毁了。通常来说,Startedservice只会做单一的操作,并且不会返回给调用者返回值。比如:它可以通过网络下载或者是上传文件。当操作结束的时候,service要手动把自己停止掉。Bound当其他组件通过调用bindService()绑定到service的时候,service就是"bound"的。boundservice提供了客户端/服务端的接口,允许组件和service进行交互,发送请求,获取结果,甚至是做跨进程的操作。boundservice只存活于其他组件绑定在它上面的时候,多个组件可以同时绑定到一个service,但是,当所有的组件同时解绑以后,service就被销毁了。尽管本文档是分开讨论这两种类型的service的,但是你的service可以同时支持这两种类型,service可以是started(无限运行)同时还允许绑定。这仅仅取决于你是否实现了下面的回调:onStartCommand()允许其他的组件start一个service,onBind()允许绑定service。不管你的service是started还是bound,应用的其他组件都可以使用这个service(甚至是别的应用)。就如同别的组件都可以使用一个Activity一样,通过Intent来启动它。但是,你也可以在manifest文件中把service声明成应用私有的,这就阻止了别的应用访问它。更多信息请参考“在manifest文件中声明service”(/gui...ices.html#Declaring)这一节。注意:service是运行在宿主进程的主线程的,service并不会创建它自己的线程,并不会运行在单独的进程中,除非你指定了。这意味着,如果你的service要做一些耗CPU或者是阻塞的操作(比如:播放MP3或者是网络请求),你需要在service内部手动创建一个新的线程来做这样的操作。通过使用单独的线程,会降低ANR的风险,让主线程可以专注于UI操作。service基础要创建一个service,必须要创建Service(或者是Service子类)的子类。在你的实现中,你要重写一些回调方法,它们用来处理service的一些关键的生命周期,并且提供组件绑定到service的机制,如果合适的话。要重写的最重要的回调是:onStartCommand()当别的组件通过调用startService()来启动service的时候,系统会调用这个方法。一旦这个方法开始执行,service就启动起来并在后台无限运行。如果你覆盖了这个方法,你还要负责在service的工作结束以后通过调用stopSelf()或者stopService()销毁掉service。(如果你只是想提供绑定就不需要实现这个方法)onBind()当其他的组件通过调用bindService()绑定到service(比如做RPC)的时候,系统会调用这个方法。实现这个方法的时候,必须要通过返回一个IBinder来给客户端提供一个用来和service进行交互的接口。一般都要实现这个方法,但是如果你不允许绑定的话,可以返回null。onCreate()当service首次启动的时候,系统会调用这个方法,只会执行一次(在调用onStartCommand()或者onBind()之前)。如果service已经在运行了,这个方法是不会被调用的。onDestroy()当service不再被使用或者是被销毁的时候系统会调用这个方法。你的service要实现这个方法来做一些清理资源的工作,比如:线程啊,监听啊,广播接收器啊等等。这是service收到的最后一个回调。如果一个组件通过startService()启动一个service(会导致系统调用onStartCommand()),service会一直运行,一直到它调用stopSelf()或者是别的组件调用stopService()来把它停止掉。如果一个组件通过bindService()启动一个service(onStartCommand()不会被调用),service只存活于绑定到它的组件上。一旦service跟所有的客户端解绑,它就会被系统结束掉。Android系统只会在系统的内存不够用的时候才会强制杀掉service,系统必须能够给拥有用户焦点的activity提供系统资源。如果service被绑定到了拥有用户焦点的activity上,它很可能不会被杀死。如果service声明成了前台运行的,一般不会被杀死。其他情况下,如果service是被started并且是长时间运行的,系统会随着时间的推移把它放到后台任务列表的靠后的位置,它就会变得易于被杀掉。如果你的service是被started,你必须要让它能优雅的处理系统的restart。如果系统杀掉了你的service,一旦资源可用,系统会立马restart被杀掉的service(当然这也取决于onStartCommand()的返回值)。想了解更多关于系统可能会杀掉service的信息,参考:进程和线程(/gui...es-and-threads.html)。下面的章节,你会学到如何创建各种类型的service,还有如何在其他组件中使用service。在manifest文件中声明service跟Activity类似(还有其他组件),你必须要在manifest文件中声明所有的service。要声明一个service,添加<service>元素作为<application>的子元素,比如:<manifest...>

...

<application...>

<serviceandroid:name=".ExampleService"/>

...

</application></manifest>想了解更多关于在manifest声明service的信息,参考<service>元素大全(/gui...ervice-element.html)。<service>元素还有很多其他的属性,可以用来定义启动service的权限或者是service运行的进程。android:name属性是唯一必须的,它指定了service的类名。一旦你发布了应用以后,就不应该再修改这个名字了。假如你修改了,就会让用明确Intent来start或者是bindservice的代码有crash的风险。为了确保你的应用是安全的,当start或者是bind一个service的时候总是使用明确的intent,并且不要给service声明intentfilter。如果允许不明确的方式来启动service非常重要,你可以给service提供intentfilter,排除掉某些组件名字。但是,你必须要用setPackage()给intent设置pachage,这给要调用的目标service提供了足够的确定性。此外,你也可以用过引入android:exported这个属性,并把它的值设置为false来确保你的service只是对你的应用可用。这就有效地防止了其他的应用启动你的service,就算是使用明确intent也没有用。创建一个StartedService如果别的组件通过调用startService()启动service的话,service就是一个startedservice,这会导致系统调用servicve的onStartCommand()方法。当service启动以后,它的生命周期跟启动它的组件的生命周期是相互独立的,service可以在后台无限的运行,就算启动它的组件已经销毁了。这种情况下,当它的任务完成以后,service就需要调用stopSelf()来停掉自己,其他的组件可以调用stopService()来停掉service。应用程序的组件比如Activity可以通过调用startService()来启动一个service,并且给service传递一个Intent,Intent就指定了要启动的service和传递给service使用的数据。service会在onStartCommand()方法中收到这个Intent。举个例子,假如一个Activity需要把数据保存到网络的数据库上,Activity可以启动一个service,通过intent传递给service要保存的数据。service在onStartCommand()方法中收到intent,连上网络,做数据库操作。当操作完成以后,service要停掉自己,然后servive就被销毁了。注意:service是运行在应用的同一个进程中,默认是运行在应用的主线程的。因此,如果当用户跟应用进行交互的时候,service做一些耗时或者是阻塞的操作的话,service会拖慢Activity的性能。为了避免影响应用的性能,你要在service内部新开一个线程。一般来说,可以通过继承两个类来创建startedservice:一个是继承ServiceService是所有service的基类。当你继承这个类的时候,要在service内部新开一个线程做繁重的操作,因为service默认是运行在应用的主线程的,它会影响应用的性能。还一个是继承IntentService它是Service的子类,它内部使用了一个工作线程来处理所有的请求,一次一个。如果你的service不需要同步与处理多个请求的话,这将是最佳的选择。你所要做的仅仅是实现onHandleIntent()方法,它会接收请求的intent,因此你就可以做后台任务。下面的章节讲述了如何用这两个类实现service。继承IntentService类因为大多数的startedservice都不需要处理并发的请求,因此使用IntentService可能是最优的方案。IntentService会做如下的事情:(1)创建一个默认的工作线程,它用来执行传递到onStartCommand()的intent,并且是跟应用的主线程独立的。(2)创建一个工作队列。每次只传递一个intent到onHandleIntent()方法,因此就不需要担心多线程的问题了。(3)当所有的请求都处理完以后,service会自动停止掉,因此不需要调用stopSelf()。(4)提供了onBind()的默认实现,方法会返回null。(5)提供了onStartCommand()的默认实现,会把intent发送到工作队列,然后发送给onHandleIntent()。所有这些以后,你所需要做的仅仅是实现onHandleIntent()来完成客户的工作(当然你也可以给service提供构造函数)。下面是一个实现了IntentService的例子:publicclassHelloIntentServiceextendsIntentService{

/**

*Aconstructorisrequired,andmustcallthesuperIntentService(String)

*constructorwithanamefortheworkerthread.

*/

publicHelloIntentService(){

super("HelloIntentService");

}

/**

*TheIntentServicecallsthismethodfromthedefaultworkerthreadwith

*theintentthatstartedtheservice.Whenthismethodreturns,IntentService

*stopstheservice,asappropriate.

*/

@Override

protectedvoidonHandleIntent(Intentintent){

//Normallywewoulddosomeworkhere,likedownloadafile.

//Foroursample,wejustsleepfor5seconds.

longendTime=System.currentTimeMillis()+5*1000;

while(System.currentTimeMillis()<endTime){

synchronized(this){

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论