Android学习笔记2-1--组件4--Service

来源:互联网 发布:阿普利亚200圣甲虫数据 编辑:程序博客网 时间:2024/06/11 21:43

组件简介

使用Service可以在后台执行长时间的操作且并不与用户产生UI交互。其他的应用组件可以启动Service,即便用户切换了其他应用,启动的Service仍可在后台运行。一个组件可以与Service绑定并与之交互,甚至是跨进程通信(IPC)。例如一个Service可以在后台执行网络请求、播放音乐、执行文件读写操作或者与provider交互等。

组件定义

组件声明

# 除此之外,在<service>标签中还可以配置其他属性,比如,需要启动该service所需的权限、该service应运行在哪个进程中等。<service    android:name=".TService"    android:process=":remote"  //将本地服务设置成远程服务    android:exported="true">      //设置可被其他进程调用    //该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。    //此处Intent的action必须写成“服务器端包名.aidl文件名”    <intent-filter>        <action android:name="scut.carson_ho.service_server.AIDL_Service1"/>    </intent-filter></service>

若不确定该启动哪个Service,那么可以在中配置intent-filter,并在Intent中排除该Service,但必须调用Intent的setPackage()方法,来为启动的service消除歧义。

注:setPackage()方法传入一个String参数,代表一个包名。该方法表示该Intent对象只能在传入的这个包名下寻找符合条件的组件,若传入null,则表示可以在任意包下寻找。

组件方法

一般使用如下两种方式创建一个start Service:

继承Service类:请务必在Service中开启线程来执行耗时操作,因为Service运行在主线程中。

继承IntentService类:IntentService继承于Service,若Service不需要同时处理多个请求,那么使用IntentService将是最好选择:您只需要重写onHandleIntent()方法,该方法接收一个回传的Intent参数,您可以在方法内进行耗时操作,因为它默认开启了一个子线程,操作执行完成后也无需手动调用stopSelf()方法,onHandleIntent()会自动调用该方法。

Service类回调方法反应了Service的生命周期,并提供了绑定Service的机制。最重要的Service的生命周期回调方法如下所示:

onStartCommand():当其他组件调用startService()方法请求启动Service时,该方法被回调。一旦Service启动,它会在后台独立运行。当Service执行完以后,需调用stopSelf()stopService()方法停止Service。(若您只希望bind Service,则无需调用这些方法)onBind():当其他组件调用bindService()方法请求绑定Service时,该方法被回调。该方法返回一个IBinder接口,该接口是Service与绑定的组件进行交互的桥梁。若Service未绑定其他组件,该方法应返回nullonCreate():当Service第一次创建时,回调该方法。该方法只被回调一次,并在onStartCommand()onBind()方法被回调之前执行。若Service处于运行状态,该方法不会回调。onDestroy():当Service被销毁时回调,在该方法中应清除一些占用的资源,如停止线程、接触绑定注册的监听器或broadcast receiver等。该方法是Service中的最后一个回调。

如果某个组件通过调用startService()启动了Service(系统会回调onStartCommand()方法),那么直到在Service中手动调用stopSelf()方法、或在其他组件中手动调用stopService()方法,该Service才会停止。多个组件可同时与Service绑定,当任一组件调用stopService,该Service就会结束。

若系统正在处理多个调用onStartCommand()请求,那么在启动一个请求时,您不应当在此时停止该Service。为了避免这个问题,您可以调用stopSelf(int)方法,以确保请求停止的Service时最新的启动请求。这就是说当调用stopSelf(int)方法时,传入的ID代表启动请求(该ID会传递至onStartCommand()),该ID与请求停止的ID一致。则如果在调用stopSelf(int)之前,Service收到一个新的Start请求,ID将无法匹配,Service并不会停止。

如果某个组件通过调用bindService()绑定了Service(系统不会回调onStartCommand()方法),只要该组件与Service处于绑定状态,Service就会一直运行,当Service不再与组件绑定时,该Service将被destroy。多个组件可同时与Service绑定,当组件与Service交互结束后,可调用unbindService()方法解绑,当全部解绑完成后该Service才会结束。

AIDL使用

为了让远程Service与多个应用程序的组件进行跨进程通信,需要使用AIDL或看这里。以下是两个进程角色的具体使用步骤demo看这里:

服务器端(Service)

步骤1:新建定义AIDL文件,并声明该服务需要向客户端提供的接口。
步骤2:在Service子类中创建实现AIDL中定义的接口方法的实例,并定义生命周期的方法,要在onBind中返回刚才的实例。
步骤3:在AndroidMainfest.xml中注册服务并且声明为远程服务。

客户端(Client)

步骤1:拷贝服务端的AIDL文件到目录下。
步骤2:在ServiceConnection中使用Stub.asInterface(IBinder)接口获取服务器的Binder,根据需要调用服务提供的接口方法。
步骤3:通过Intent指定服务端的服务名称和所在包,绑定远程Service。

组件调用

Services有两种启动形式和一种特殊形式:

Started:其他组件调用startService方法启动一个Service。一旦启动Service将一直运行在后台,即便启动Service的组件已被destroy。通常一个被start的Service会在后台执行单独的操作,也并不给启动它的组件返回结果。比如一个start的Service执行在后台下载或上传一个文件的操作,完成之后Service应自己停止。

Bound:其他组件调用bindService方法绑定一个Service。一个bound service仅在有组件与其绑定时才会运行,多个组件可与一个service绑定。service不再与任何组件绑定时,该service会被destroy。通过绑定方式启动的Service是一个client-server结构,该Service可与绑定它的组件进行交互。注意bindService方法需要一个ServiceConnection参数。

startForeground(特殊形式,非自定义):

调用startForeground()可以启动前台Service。前台Service用于动态通知消息如天气预报。该Service不易被kill。前台Service必须提供status bar,只有前台Service被destroy后,status bar才能消失。
调用stopForeground()来移除前台Service。该方法需传入一个boolean型变量,表示是否也一并清除status bar上的notification。该方法并不停止Service,如果停止正在前台运行的Service,那么notification也一并被清除。

当然service也可以同时在上述两种方式下运行。这涉及到Service中两个回调方法的执行:onStartCommand()(通过start方式启动一个service时回调的方法)、onBind()(通过bind方式启动一个service回调的方法)。

请注意:Service运行在主线程中。Service并不是一个新的线程,也不是新的进程。也就是说,若您需要在Service中执行较为耗时的操作(如播放音乐、执行网络请求等),需要在Service中创建一个新的线程。这可以防止ANR的发生,同时主线程可以执行正常的UI操作。


参考这篇文章

参考这篇文章

参考这篇文章

参考这篇文章

原创粉丝点击