安卓翻译8 Services 一

来源:互联网 发布:宝宝学字软件 编辑:程序博客网 时间:2024/03/29 14:06

原网址 http://developer.android.com/guide/components/services.html

今天平安夜啊!为毛!泪奔~~o(>_<)o~~

 

Service 是一个应用构件,它能够在后台执行耗时长的任务但是不提供用户界面。另外的应用构件能够启动一个service,并且即使用户转向另外一个应用时,它也能继续在后台运行。另外,一个构件能够绑定到一个service上来与它交互,甚至执行进程间通信。例如,一个service可能处理网络事件,播放音乐,执行文件I/O,或者与一个content provider交互,这些动作都是在后台完成的。

 

Service 本质上有两种形式

被启动

当一个应用构件(例如 一个activity)通过调用startService()来启动service,它就能被启动。一旦被启动,service就持续地运行在后台,即使启动它的构件被摧毁掉。通常情况下,一个已经启动的service执行单线操作并且不会给它的调用者返回结果。例如,它可能通过网络下载或者上传文件,当操作结束时,service应该停止它自己。

被绑定

Service能被绑定,当一个应用构件通过调用bindService()绑定它时,奇迹就发生了(这句我自己加的,哈哈)。一个被绑定的service提供一个 客户端到服务器 ②的接口,这允许构件与service交互,发送请求,得到结果,甚至做一些像通过进程来产生进程间交互③。一个被绑定的service仅仅当其他应用构件绑定到它身上时菜开始运行。多个构件能同时绑定到一个service上,但是当它们都解除捆绑时,这个service就会被摧毁。

 

尽管这个文档通常分开讨论着两种类型的service, 你的service能以两种方式工作, 它能被启动(持续运行),也能运行被绑定。这仅仅需要你实现一对回调函数中的一个:onStartCommand()允许构件启动它,onBind()运行绑定。

 

不论你的应用是否被启动,绑定或者两者同时发生,任何应用构件都能使用service(甚至从其它应用中借取),就跟这个一样——任何构件都能通过用一个Intent来启动一个activity。然而,你能在 manifest 将service声明成私有的,这就阻碍了其它应用对它的获取。这个内容会在关于 在manifest文件中声明service的章节中声明更多。

 

警告:Service运行在它宿主进程中的主线程中——service不会创建它自己的县城,也不会运行在单独的进程中(除非你另外指定)。这意味着,如果你的service将要做任何消耗CPU较多的工作或者阻塞操作(例如MP3播放或者网络任务), 你应该在service中创建一个新线程来做它。通过使用一个分离的线程,你将会减少应用无响应的风险,应用的主线程能够保持与你的activities之间的用户交互。

 

基础原理

在创建一个service之前,你必须创建一个Service类的子类(或者它的一个已经存在的子类)。在你的实现中,你必须重写一些回调函数,它们处理services生命周期的主要环节和为构件提供绑定到service上的机制,如果合适的话。你应该重写的最重要的回调函数是:

onStartCommand()

当另外一个构件,例如activity,通过调用startService()请求启动service时,系统调用这个函数。一旦这个函数执行了,service就被启动并且持续地运行在后台。如果你实现了这个的话,当它的使命完成后,结束它就是你的责任了。可以通过stopSelf()或者stopService()来停止service。(如果你只想提供绑定类型的话,就不需要实现这个函数了)。

onBind()

当另外一个构件通过调用bindService()想与service绑定时(例如执行RPC),系统会调用这个函数。在你这个方法的实现中,必须通过返回一个IBinder提供一个接口,客户端用来与service通信。你啊,必须始终实现这个方法,但是如果你不想绑定时,那么你应该返回null。

onCreate()

当service第一次被创建时,系统调用这个函数。用来执行一次性的安装过程(这是在onStartCommand(), onBind()之前调用的。如果service已经运行的话,这个函数就不会被调用。

onDestroy()

当service没有价值并且将要被销毁时,系统调用这个函数。Service应该实现这个方法来清理一些资源,例如线程,注册的监听器,receivers,等等。这是service最后收到的一个调用(感觉好悲凉啊,就像英雄临终前的不甘一样)。


如果一个组件通过调用startService()调用service时(这会导致对onStartCommand()的调用),那么service会知道它通过stopSelf()或者另外一个组件通过调用stopService()来结束它之前,它会一直保持运行的。

如果一个组件通过调用bindService()来创建service(同时onStartCommand()没被调用),那么仅当组件绑定它身上时,service就会运行。一旦service从所有的客户上解绑后,系统就会销毁它。


安卓系统会强制停止一个service,这仅当内存很低和它必须为有着用户焦点的activity恢复系统资源时才会发生。如果service绑定到有着用户焦点的activity上,那么它被杀死的概率很低,如果service被声明成在前台运行,那么它几乎不可能被杀死。否则,如果service被启动并长时间运行,那么系统将会随着时间降低它在后台任务列表中的位置,并且service将会变得极其容易得被杀死——如果你的service已经启动,那么你必须设计它,以让它以合适的方式被系统重启。如果系统系统杀死了你的service,一旦系统资源变得可用时它就会重启它(但是这依赖于你从onStartCommand()返回的值,稍后讨论)。关于系统可能销毁service的更多信息,请看 进程和线程 章节。


在下面的章节中,你将会看到你怎样创建每种类型的service和怎样从其它应用组件中使用它。

在manifest中声明service

就跟activities一样还有其它组件,你必须在你的应用manifest文件中声明所有services。

为了声明service,增加一个<service>标签做为<application>标签的子元素。例如

<manifest ... >  ...  <application ... >      <service android:name=".ExampleService" />      ...  </application></manifest>

更多在manifest文件中声明service信息请看 <service>标签简介。

还有一些其它你可以包含进<service>中的属性,它们用来定义像请求启动service的权限,service应该运行在哪个进程的性质。android:name 属性是仅有的必要属性——它指定service的类名。一旦你发布了你的应用,你应该不再改变它的名字,因为如果你那样做了的话,你会有破坏代码的风险,这是由于它(应用)依赖着明确的intent来启动,或者绑定service(读这篇博客,Things That Cannot Change)。

为了你确保你的应用的安全性,应总是用一个明确的intent,当你启动或者绑定你的Service时,并且不要给service声明intent过滤器。如果这重要到你允许模糊启动你的service④, 那么你能够给你的services提供intent过滤器和同Intent中排除构件名字,但是之后你必须用setPackage()给intent设置 package,这会给目标service提供有效的歧义消除。

另外,你能通过包含 android:exported 属性并且将它的值设为“false”, 来确保你的service仅对自己的应用可用。这会有效的阻止其它应用启动你的service,甚至使用明确的intent。



 

 

 

这句话原话是 A service can essentially take twoforms:翻译过来很不顺畅

client-server

do so across process withinterprocess conmmunication(IPC)

 ④if it's critical that you allow for some amount of ambiguity as to which service starts

0 0