服务是应用程序组件,可以在后台来执行长时间的操作,并且没有用户交互界面。另外一个应用组件可以开启一个服务,即使在用户切换到其他应用程序后依然可以在后台继续执行。此外,一个组件可以绑定一个服务并且与其进行交互。例如,一个服务可以在后在处理网络传输,播放音乐,执行文件读写,或者和内容提供者进行交互。

有三种不同类型的服务:

前台

一个前台服务执行一些用户可以看到的操作。例如,一个音乐app可以使用前台服务来展示音乐播放进度。前台服务必须展示Notification.当用户不再同此app交互时,前台服务依然可以继续运行。

后台

后台服务执行不被用户注意到的操作。比如,一个app使用服务来操作存储,通常就是后台服务。

注意:如果你的app targets api是level 26或者更高,那么当app不在前台的时候,系统就会请加做后台服务的约束。类似这种情况,app就应当使用 scheduled job 来代替了。

绑定

当调用bindService()的时候,一个服务就同组件绑定了。一个绑定服务提供了一个client-servier的接口允许组件同服务进行交互,发送请求,接收结果,等。只有在其他应用程序组件绑定了这个服务,服务才会运行。一个服务一次可以绑定多个组件,当所有的组件都解绑后,服务就销毁了。

onStartCommand() 来允许组件启动服务, onBind()允许绑定服务。

不论你的服务是否启动,绑定,或者两者都是,任何的应用组件都可以使用这个服务。(设置可以从独立的应用程序)

Declaring the service in the manifest.讲解了如何声明一个服务的方法。

注意:服务运行在主线程上。服务本身不会创建自己的线程也不会单独运行除非你有特别指出。通过使用独立的线程,你可以降低应用程度服务响应(ANR)的错误。并且应用程序的主线程可以保留下来和用户进行交互。

选择服务还是线程

服务是可以在后台运行的组件。甚至当你的应用程序没有和用户交互的时候,因此你应当仅在需要的时候创建服务。

如果你必须在主线程外执行操作,并且需要同用户进行交互的时候进行这个操作,那么就应当使用线程。比如,如果你想播放音乐,但是只有当你的activity运行的时候才进行播放,你就可以在onCreate()中创建一个线程,onStart()中启动这个线程, onStop()中停止这个线程。同时可以考虑使用AsyncTask or HandlerThread而不是线程来实现这个目的。相关的内容可以查看Processes and Threading

基本操作

想创建一个服务,首先创建Service的子类或者使用已经存在的Service的子类。在你的实现中,你必须复写回调方法,来处理服务声明周期并且提供允许组件绑定到服务的机制。以下是几个关键的回调方法:

startService() 开启服务

此方法开启服务,当调用此方法后,服务就被启动并且可以在后台进行运行。调用此方法开启服务后,需要调用 stopSelf() or stopService()来停止服务的运行。如果仅仅是想绑定服务,就不需要实现这个方法。

onBind() 绑定服务

你必须提供接口,用户可以同服务进行交互。如果不允许绑定,就在此方法中返回null

onCreate() 创建服务

先于onStartCommand() or onBind())执行。如果服务已经运行了,那么这个方法就不会再次调用。

onDestroy() 注销服务

当服务不再使用被销毁的时候,系统就会调用这个方法。如果组件调用了bindService()来创建服务,并且没有调用onStartCommand(),那么服务仅仅在有组件绑定的情况下运行,当所有的服务都解绑后,系统就会销毁这个服务。

Android系统只有当内存低的时候会停止服务。如果服务同用户activity绑定了且获取了焦点,那么就不太容易被杀掉。如果服务声明为前台运行,那么就很难被杀掉。如果服务开启并且长时间运行,系统就会降低他在后台任务列表中的位置,而且很容易被杀掉。如果系统杀掉了服务,会在资源可用时再次启动服务,但是这个依赖于onStartCommand()返回的值。

接下来,你会看到如何创建和绑定服务,startService() and bindService() 和如何在另外一个应用程序组件中使用他们。

在manifest文件中声明服务

使用关键元素<service>

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

</application></manifest>

注意:为了确保你app的安全性,通常当开启服务时会使用显示intent并且不会为你的服务声明intent filter。使用隐式intent启动服务是非常危险的,因为你不确定服务会回应intent,用户也无法看到服务启动。android5.0以后,如果使用bindService()和隐式intent的方式,系统会抛出异常。

用户可以在设备上看到运行的服务。也可以停掉这些服务。为了避免你的服务被用户突然停掉,你需要为<service> 元素添加android:description 属性。在描述中,提供简单的服务介绍等。

创建启动服务

注意:默认的,服务要在主线程上被声明和执行。当用户同activity交互时,服务会影响activity的展示。为了防止这个问题,可以考虑开启新的线程来启动服务。

可以通过两个类来创建启动服务

Service

所有服务的基础类。当扩展这个类的时候,创建新的线程会显得很重要。默认服务会在应用程序的主线程运行,这样可能会影响应用程序运行效率。

IntentService

service子类,使用工作线程管控启动请求。如果你的服务不需要同时处理多个请求,这种方式是最好的选择。实现 onHandleIntent(),会接收到每一个启动请求的intent,这样就可以完成后台任务了。

实现步骤

1. 扩展IntentService类

因为多数的启动服务不需要同时处理多个请求,因此最好通过IntentService类实现服务

2. 默认创建了工作线程来执行所有传递给onStartCommand()的intents,从而同主线程分离

3. 创建了工作队列,保证一次传递一个intent到onHandleIntent()予以实现,因此不用担心多线程的问题

4. 一旦所有的服务都处理完毕了,就会停止服务,因此不用显示调用stopSelf().

5. 提供了onBind()的默认实现并且返回null

6. 提供了onStartCommand()的默认实现,把intent发送到工作队列中然后发送到 onHandleIntent()执行

你所有需要做的准备:一个构造方法和onHandleIntent()的实现

如果你也决定复写一些重载方法,比如onCreate(), onStartCommand(), or onDestroy(), 就要保证调用了super方法。

扩展Service类

可以发现使用Service要远远比使用IntentService复杂。

START_NOT_STICKY

如果系统在onStartCommand() 返回后杀掉了服务,那么除非有intents需要传递,否则不要重复创建服务。在不必要并且你的应用程序可以简单重启任何未结束的工作的时候,这个是避免启动服务的最安全的选择。

START_STICKY

如果系统在onStartCommand() 返回后杀掉了服务,重新创建了service并且调用了 onStartCommand(),但是不会传递最后的intent。系统会调用 onStartCommand()返回null intent,除非有intents来启动这个服务。这种情况下,intents会被投递。这个非常适合媒体播放器(或者类似的服务)。不执行命令但是会一直运行等待任务派发。

START_REDELIVER_INTENT

如果系统在执行完onStartCommand() 之后杀掉了服务,重新创建了服务并且调用了 onStartCommand() 处理完了所有的intent。任何的等待状态的intents都会依次被投递。这类服务例如需要立即恢复的情况,比如下载文件。

例子程序: MessagingService sample on GitHub.

启动服务

可以通过传递一个intent给startService() 或者 startForegroundService()

Note: 如果你的app targets是api level 26或者更高,除非app在前台运行,否则系统会对创建或者使用后台服务做更大的限制。如果app需要创建前台的服务,app应当调用startForegroundService().这个方法会创建一个后台服务,但是方法信号会是的服务自身到前台。一旦服务被创建,就必须在5秒内调用startForeground()方法

停止服务

一个启动的服务必须管理自己的声明周期。也就是说,除非服务本身必须重新获得系统内存并且需要继续运行,否则系统不会停止或者销毁服务。用户需要调用stopSelf() 来停止服务。或者其他组件可以通过调用stopService(). 来停止服务

创建绑定服务

绑定服务允许应用组件通过调用bindService()来绑定创建一个长链接。绑定服务不允许组件通过startService().来启动服务。

当需要同activity进行交互,或者应用程序间进行通讯,就可以创建服务绑定。

为了创建服务绑定,需要实现onBind()回调方法并且返回 IBinder 来确定同服务通信的接口。其他的应用组件可以调用 bindService() 来检索接口并且调用服务方法。不需要停止服务

创建服务绑定,必须定义接口指定client如何同服务通信。这个接口必须实现了IBinder并且必须服务必须从onBind()方法返回。在client接收到IBinder后,就可以通过接口开始同服务交互了。

多个client可以同时绑定到服务。unbindService() 来解绑,系统就会销毁掉服务了。

有多种方式来实现服务绑定。实现方式比启动服务要复杂。详情可以查看Bound Services.

向用户发送通知

当服务运行是,可以使用Toast Notifications或者Status Bar Notifications.来通知用户。

在前台运行服务

前台服务,当系统因为内存紧张杀掉服务时,用户可以注意到。前台服务必须提供status bar通知。而且notification无法被消除掉除非服务被停止或者从前台移除掉。

Caution: 限制你的app使用前台服务的个数

你应该只使用一个前台服务,当你的app需要执行任务且可以被用户关注到,甚至当用户不直接同app进行交互的时候。由于这个原因,前台服务必须展示status bar notification,优先级为PRIORITY_LOW或者更高。确信用户可以关注到app运行情况。

例如,音乐播放器应当设置为前台服务。

Note: android 9或者更高版本,用户使用前台服务必须请求 FOREGROUND_SERVICE 权限. 如果app api level 28或者更高,当创建前台服务而且不请求FOREGROUND_SERVICE,系统会抛出SecurityException.

请求一个前台服务,需要调用startForeground()

管理服务的生命周期

服务从创建到销毁,可以遵循两个步骤

启动服务

startService(). 可以使用 stopSelf().  stopService(). 来停止服务,调用启动服务后必须调用停止方法

绑定服务

bindService(). unbindService().

Note: Unlike the activity lifecycle callback methods, you are not required to call the superclass implementation of these callback methods.

Figure 2. The service lifecycle. The diagram on the left shows the lifecycle when the service is created with startService() and the diagram on the right shows the lifecycle when the service is created with bindService().

详情可以查看Bound Services

Services-服务相关推荐

  1. 远程桌面无法连接服务器,启动Terminal Services 服务报1053错误

    今天碰到一棘手问题,一上午数据库服务器都无法连接,远程桌面也连不上了,但是可以PING通.项目组的同事一直反映数据库无法连接,耽误工作进度,真急人啊. 跑到机房一看,机器轰轰巨响,进入桌面,点个鼠标半 ...

  2. 基于Spring Boot应用Apache CXF发布Web Services服务

    记录:298 场景:使用Spring Boot应用Apache CXF发布Web Services服务,实现跨系统之间交互接口. 版本: JDK 1.8 Spring Boot 2.6.3 Apach ...

  3. Zend Studio13.6.1创建web services服务

    Zend Studio13.6.1创建web services服务 一.开发环境 1.1 zendstudio13.6.1 1.2 apache httpd-2.4.46-o111j-x64-vc15 ...

  4. 手动启动Remote Desktop Services服务,报错提示:“系统无法找到指定文件” ,该如何解决

    手动启动Remote Desktop Services服务,报错提示:"系统无法找到指定文件" 解决方法: 1.打开regedit,找到路径HKEY_LOCAL_MACHINE\S ...

  5. w ndows更新,如何解决 Wndows 7 安装更新时遇到的 8024402f 错误及修复损坏的 Cryptographic Services 服务.pdf...

    如何解决 Wndows 7 安装更新时遇到的 8024402f 错误及修复损坏的 Cryptographic Services 服务 嚼 华 刷 亡 披 风 秸 凶 毛 搪 迎 腾 技 班 籽 办 纯 ...

  6. WCF Data Services服务端处理汇总

    和可以在客户端直接使用的查询对应,在服务端也有很多可以增强的功能 Service Operations 自己发布一些业务逻辑的处理 Service operations enable you to e ...

  7. 基于soap 的 python web services 服务开发指南

    文章大纲 序言 相关概念 SOA web services SOAP WSDL UDDI 环境搭建 我们使用 python 3.6 这个较新python 版本 服务端开发 客户端开发 suds-jur ...

  8. 本地 Services(服务)

    Services 什么是Services android中服务是运行在后台的东西,级别与activity一样.既然说service是运行在后台的服务,那么它就是不可见的,没有界面的东西.可以启动一个服 ...

  9. Windows server 2008启动remote dosktop services服务报错1079

    原创 欢迎转载,届时请注明出处 报错场景 今天,刚开始启动win server的远程连接服务(remote desktop services)时 该服务可以正常启动,然后选择了  "计算机- ...

  10. .NET Web Services服务

    一.简介 Web Services 可使您的应用程序成为 Web 应用程序. Web Services 通过 Web 进行发布.查找和使用. 1.什么是Web Services? Web Servic ...

最新文章

  1. 在数量上超过微型计算机的是什么,在数量上超过微型计算机的是什么计算机
  2. Windows 8 :妥协的产物
  3. mysql mgr故障恢复实现_MGR实现分析 - 成员管理与故障恢复实现
  4. 正则(身份证,手机号,邮箱,正整数)
  5. python / 内置的数据结构概述
  6. python3.70 wxpy_python3.5中的wxpydeprectionwarning
  7. 一个网卡配置两个不同网段的IP地址(比如应用道闸项目)
  8. 如何在html嵌入html网页
  9. 基于python下django框架 实现闲置物品二手跳蚤市场交易系统详细设计
  10. Mac/iOS开发工程师 常用的软件 史上最全版
  11. PHP基础教程(第4版)电子书pdf下载
  12. Java Springboot 使用 OpenOffice 实现Excel转PDF
  13. 网络存储-详解NAS网络存储
  14. 计算机词汇怎么背,如何背诵英语词汇更有效?
  15. 什么是域,域树,深林?
  16. 固态硬盘和机械硬盘的区别
  17. html 好看的数据表格,CSS制作好看的网页表格
  18. 数据结构当中的二元组详解
  19. DBA生涯之如何成为高级DBA
  20. 【好奇心驱动力】e-paper电子价签从零开始折腾记录

热门文章

  1. 初探串口输出六轴陀螺仪
  2. 模拟登陆 - 破解12306验证码
  3. h5 or web缅甸语乱码问题
  4. 华为服务器驱动下载及安装
  5. Cas(05)——修改Cas的其它配置
  6. 整理各类IT编程视频教程下载地址
  7. 【软件测试大赛Web应用省赛】跳坑记录
  8. 消防工程师 2.4 自动喷水灭火系统-喷头选型
  9. vtp协议服务器配置,Cisco思科交换机VTP协议三种模式区别?
  10. 关于ppa源404的一个解决方法