万书网 > 文学作品 > Android从入门到精通 > 第140页

第140页



Service类的继承关系如图13.1所示。



图13.1 Service类继承关系

13.1.3 Service的声明

类似于Activity和其他组件,开发人员必须在应用程序配置文件中声明全部的Service。为了声明Service,需要向标签中添加子标签,子标签的语法如下:




android:exported=["true"  |  "false"]



android:icon="drawable  resource"



android:label="string  resource"



android:name="string"



android:permission="string"



android:process="string"  >



.  .  .





各个标签属性的说明如下:

[√]android:enabled

服务能否被系统实例化,true表示可以,false表示不可以,默认值是true。标签也有自己的enabled属性,用于包括服务的全部应用程序组件。的enabled属性必须同时设置成true(两者的默认值都是true)才能让服务可用。如果任何一个是false,服务被禁用并且不能实例化。

[√]android:exported

其他应用程序组件能否调用服务或者与其交互,true表示可以,false表示不可以。当该值是false时,只有同一个应用程序的组件或者具有相同用户ID的应用程序能启动或者绑定到服务。

默认值依赖于服务是否包含Intent过滤器。若没有过滤器,说明服务仅能通过精确类名调用,这意味着服务仅用于应用程序内部(因为其他程序可能不知道类名)。此时,默认值是false;若存在至少一个过滤器,暗示服务可以用于外部,因此默认值是true。

该属性不是限制其他应用程序使用服务的唯一方式。还可以使用permission属性限制外部实体与服务交互。

[√]android:icon

表示服务的图标。该属性必须设置成包含图片定义的可绘制资源引用。如果没有设置,使用应用程序图标取代。

服务图标不管在此设置还是在标签设置,都是所有服务的Intent过滤器默认图标。

[√]android:label

显示给用户的服务名称。如果没有设置,使用应用程序标签取代。

服务标签不管在此设置还是在标签设置,都是所有服务的Intent过滤器默认标签。

标签应该设置为字符串资源引用,这样可以像用户界面的其他字符串那样本地化。然而,为了开发时方便,也可以设置成原始字符串。

[√]android:name

实现服务的Service子类名称,应该是一个完整的类名,如com.mingrisoft.RoomService。然而,为了简便,如果名称的第一个符号是点号(如.RoomService),则会增加在标签中定义的包名。

一旦发布了应用程序,不应该再修改子类名称。该属性没有默认值并且必须指定。

[√]android:permission

实体必须包含的权限名称,以便启动或者绑定到服务。如果startService()、bindService()或stopService()方法调用者没有被授权,方法调用无效,并且Intent对象也不会发送给服务。

如果没有设置该属性,使用标签的permission属性设置给服务。如果标签的permission属性都未设置,服务不受权限保护。

[√]android:process

服务运行的进程名称。通常,应用程序的全部组件运行于为应用程序创建的默认进程。进程名称与应用程序包名相同。标签的process属性能为全部组件设置一个相同的默认值。但是组件能用自己的process属性重写默认值,从而允许应用程序跨越多个进程。

如果分配给该属性的名称以冒号(:)开头,仅属于应用程序的新进程会在需要时创建,服务能在该进程中运行;如果进程名称以小写字母开头,服务会运行在以此为名的全局进程,但需要提供相应的权限。这允许不同应用程序组件共享进程,减少资源使用。





13.2 创建Started  Service

教学录像:光盘\TM\lx\13\  创建Started  Service.exe

Started  Service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。

当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。

应用程序组件(如Activity)能通过调用startService()方法和传递Intent对象来启动服务,在Intent对象中指定了服务并且包含服务需要使用的全部数据。服务使用onStartCommand()方法接收Intent。

例如,假设Activity需要保存一些数据到在线数据库。Activity可以启动伴侣服务并通过传递Intent到startService()方法来发送需要保存的数据。服务在onStartCommand()方法中收到Intent,联入网络并执行数据库事务。当事务完成时,服务停止自身并销毁。

Android提供了两个类供开发人员继承以创建启动服务。

[√]Service:这是所有服务的基类。当继承该类时,创建新线程来执行服务的全部工作是非常重要的。因为服务默认使用应用程序主线程,这可能降低应用程序Activity的运行性能。



[√]IntentService:这是Service类的子类,它每次使用一个工作线程来处理全部启动请求。在不必同时处理多个请求时,这是最佳选择。开发人员仅需要实现onHandleIntent()方法,该方法接收每次启动请求的Intent以便完成后台任务。

13.2.1 继承IntentService类

因为多数启动服务不必同时处理多个请求(在多线程情境下会很危险),所以使用IntentService类实现服务是非常好的选择。IntentService可完成如下任务:

[√]创建区别于应用程序主线程的默认工作线程来执行发送到onStartCommand()方法的全部Intent。



[√]创建工作队列,每次传递一个Intent到onHandleIntent()方法实现,这样就不必担心多线程。



[√]所有启动请求处理完毕后停止服务,这样就不必调用stopSelf()方法。



[√]提供onBind()方法默认实现,其返回值是null。



[√]提供onStartCommand()方法默认实现,它先发送Intent到工作队列,然后到onHandleIntent()方法实现。