首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android service详解(1)

android service详解(1)

作者头像
随心助手
发布2019-10-15 18:18:54
1.3K0
发布2019-10-15 18:18:54
举报
文章被收录于专栏:nginx遇上redisnginx遇上redis

一、Service(服务)概述

(1)Service是Android系统中的四大组件之一。

(2)Service是可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响,除非系统必须回收内存资源,否则系统不会停止或销毁Service。

(3)此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。

(4)Service默认并不会运行在子线程中,Service是在主线程里执行操作的,因此,不要在Service中执行耗时的操作,避免因为执行耗时操作而导致ANR(ApplicationNot responding),除非你在Service中创建了子线程来完成耗时操作。

二、两种启动方式

服务基本上分为两种形式:

(1)startService

当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“start”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响。已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。例如,它可能通过网络下载或上传文件。操作完成后,服务会自行停止运行。

(2)bindService

当应用组件通过调用 bindService() 绑定到服务时,服务即处于“bind”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

虽然上文是分开概括讨论这两种服务,但是您的服务可以同时以这两种方式运行,也就是说,它既可以是start服务(以无限期运行),也允许bind。问题只是在于您是否实现了一组回调方法:onStartCommand()(允许组件启动服务)和 onBind()(允许绑定服务)。

无论应用是处于启动状态还是绑定状态,抑或处于启动并且绑定状态,任何应用组件均可像使用Activity 那样通过调用 Intent 来使用服务(即使此服务来自另一应用)。不过,可以通过AndroidManifest.xml将服务声明为私有服务,并阻止其他应用访问。

三.生命周期

Service生命周期。左图显示了使用 startService() 所创建的服务的生命周期,右图显示了使用 bindService() 所创建的服务的生命周期。

四.使用Service的步骤

1.定义一个类继承Service(或使用它的一个现有子类如IntentService)

2.在Manifest.xml文件中配置该Service

3.使用startService()或bindService()方法启动该Service

4.不再使用时,调用stopService()、stopSelf()或unbindService()方法停止该服务

4.1定义一个类继承Service

public class MService extends Service {  
    /**
    * 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。
    * 如果服务已在运行,则不会调用此方法。该方法只被调用一次
    */
    @Override  
    public void onCreate() {  
        super.onCreate();  
    }  
    /**
    * 每次通过startService()方法启动Service时都会被回调。
    */
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        return super.onStartCommand(intent, flags, startId);
    }  
    /**
    * 服务销毁时的回调
    */
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
    }  
    /**
    * 绑定服务时才会调用 必须要实现的方法
    */
    @Override  
    public IBinder onBind(Intent intent) {  
        return null;  
    }  
  
}  

虽然这个Service什么都没干,但实际上它是Service组件的框架,如果希望Service组件做某些事情,那么只要在onCreate()或onStartCommand()方法中定义相关业务代码即可.

4.2在清单文件声明

定义了上面的Service之后,接下来需要在Androidmaniferst.xml文件中配置该Service,配置Service使用<service../>元素。与配置Activity显示的是,配置Service时也可为<service../>元素配置<intent-filter.../>子元素,用于说明该Service可被那些Intent启动。

<application
        ...
        <service android:name=".MService" >
            <intent-filter>
                <action android:name="..." />
            </intent-filter>
        <service/></application>

Service包含的属性有

<service android:enabled=["true" | "false"]
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:isolatedProcess=["true" | "false"]
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string" >
    . . .
</service>

属性

说明

description

对服务进行描述,属性值应为对字符串资源的引用,以便进行本地化

directBootAware

设置是否可以在用户解锁设备之前运行,默认值为“false”

enabled

设置是否可以由系统来实例化服务。< application >元素有自己的enabled属性,适用于包括服务在内的所有应用程序组件。要启用服务,< application >和< service >属性必须都为“true”(默认情况下都为true)。如果其中一个是“false”,则服务被禁用

exported

设置其他应用程序的组件是否可以调用本服务或与其交互,如果可以,则为“true”。当值为“false”时,只有同一个应用程序或具有相同用户ID的应用程序的组件可以启动该服务或绑定到该服务。该属性的默认值取决于服务是否包含Intent filters。没有任何过滤器意味着它只能通过指定其确切的类名来调用,这意味着该服务仅用于应用程序内部使用(因为其他人不知道类名)。所以在这种情况下,默认值为“false”。 另一方面,如果存在至少一个过滤器,意味着该服务打算供外部使用,因此默认值为“true”

icon

服务的图标,属性值应是对drawable资源的引用。如果未设置,则将使用应用程序图标

isolatedProcess

设置该服务是否作为一个单独的进程运行,如果设置为true,此服务将在与系统其余部分隔离的特殊进程下运行,并且没有自己的权限,与它唯一的通信是通过服务API(绑定和启动)

label

可以向用户显示的服务的名称,属性值应是对字符串资源的引用

name

服务类的完全限定名

permission

设定组件必须具有的权限,得以启动服务或绑定服务。如果startService(),bindService()或stopService()的调用者没有被授予此权限,则该方法将不会工作,并且Intent对象不会传递到服务中

process

用来运行服务的进程的名称。通常,应用程序的所有组件都运行在应用程序创建的默认进程中,它与应用程序包名具有相同的名称。 < application >元素的process属性可以为所有组件设置不同的默认值,但组件可以使用自己的进程属性覆盖默认值,从而允许跨多个进程扩展应用程序

4.3启动和停止Service

通过将 Intent(指定要启动的服务)传递给 startService(),从 Activity 或其他应用组件启动服务。Android 系统调用服务的 onStartCommand() 方法,并向其传递 Intent。

Intent intent = new Intent(this, MService.class);
startService(intent);

通过将 Intent(指定要启动的服务)传递给 startService(),从 Activity 或其他应用组件启动服务。Android 系统调用服务的 onStartCommand() 方法,并向其传递 Intent。

(1)第一次调用startService()方法时,onCreate()方法、onStartCommand()方法将依次被调用,而多次调用startService()时,只有onStartCommand()方法被调用。

(2)启动服务必须管理自己的生命周期。也就是说,除非系统必须回收内存资源,否则系统不会停止或销毁服务,而且服务在onStartCommand() 返回后会继续运行。因此,服务必须通过调用 stopSelf() 自行停止运行,或者由另一个组件通过调用 stopService() 来停止它。

(3)一旦请求使用 stopSelf() 或stopService() 停止服务,系统就会尽快销毁服务。

(4)但是,如果服务同时处理多个onStartCommand() 请求,则您不应在处理完一个启动请求之后停止服务,因为您可能已经收到了新的启动请求(在第一个请求结束时停止服务会终止第二个请求)。为了避免这一问题,您可以使用stopSelf(int) 确保服务停止请求始终基于最近的启动请求。也就说,在调用 stopSelf(int) 时,传递与停止请求的 ID 对应的启动请求的 ID(传递给 onStartCommand() 的 startId)。然后,如果在您能够调用 stopSelf(int) 之前服务收到了新的启动请求,ID 就不匹配,服务也就不会停止。

注意:为了避免浪费系统资源和消耗电池电量,应用必须在工作完成之后停止其服务。如有必要,其他组件可以通过调用stopService() 来停止服务。即使为服务启用了绑定,一旦服务收到对 onStartCommand() 的调用,您始终仍须亲自停止服务。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二、两种启动方式
  • 三.生命周期
  • 四.使用Service的步骤
    • 4.1定义一个类继承Service
      • 4.2在清单文件声明
        • 4.3启动和停止Service
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档