Service是一个可以在后台执行长时间运行操作而不需要提供用户操作界面的应用组件,服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行,组件可以绑定到服务,与之进行交互,甚至执行进程间的通信。

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

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

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

注意,两种方式可以同时运行,即可以启动服务,又可以绑定,问题在于是否实现了一组回调方法onStartCommand()和onBind()。

无论应用是处于启动还是绑定,或者绑定且启动状态,都可以像使用Activity那样通过调用Intent使用服务,不过,可以通过清单文件将服务声明为私有,并阻止其他应用访问。

注意,服务在其托管进程的主线程中运行,既不创建自己的线程,也不在单独的进程中运行,这意味着,如果服务将执行任何CPU密集型工作或者阻止性操作,应在服务内创建新线程来完成该工作,通过使用单独的线程,可以降低“应用无响应”(ANR)错误的风险,而应用主线程仍可以继续专注于用户与Activity之间的交互。

创建服务

创建服务,必须创建Service的子类或者使用一个已有子类,需要重写一些回调方法,以处理服务生命周期的某些关键方面并提供一种机制将组建绑定到服务,应重写的回调方法有:

onStartCommand()---当另一个组件通过调用startService()请求启动服务时,系统将调用此方法,一旦执行此方法,服务就会启动并有可能后台无限运行,若实现此方法,在服务工作完成后,需要通过调用stopSelf()或stopService()来停止服务。

onBind()---当另一个组件通过调用bindService()与服务绑定时,系统将调用此方法,在实现此方法中,必须通过返回IBinder提供一个借口,供客户端与服务器通信。若不希望允许绑定,应返回null

onCreate()---首次创建服务时,将调用此方法来执行一次性设置,在调用onStartCommand()或onBind()之前。

onDestroy()---当服务不在使用且被销毁时,系统调用此方法,服务实现此方法,清理所有资源,这是服务接受的最后一个调用。

如果组件通过调用startService()启动服务,这会导致onStartCommand()的调用,则服务将一直运行,知道服务使用stopSlelf()自行停止运行,或由其他组件通过调用stopService()停止为止。

如果组件是通过调用bindService()来创建服务且未调用onStartCommand(), 则服务只会在该组件与其绑定时运行,一旦服务与所有客户端之间的绑定全部取消,系统便会销毁它。

在清单文件中声明服务

为确保应用安全,一定始终使用显示Intent启动或绑定Service,且不为服务声明Intent过滤器。可以添加android:exported属性,设置为”false“,确保服务仅适用于此应,可以有效阻止其他应用启动这项服务。

创建启动服务

Service---适用于所有服务的基类,扩展此类时,必须创建一个用于执行所有服务工作的新线程,因为默认时,服务将使用应用的主线程,这回降低应用正在运行的所有Activity的性能。

IntentService---这是Service的子类,使用工作线程逐一处理所有启动请求。只需要实现onHandIntent()方法即可,该方法会接受每个启动请求的Intent。

扩展IntentService类

大多数启动服务都不必同时处理多个请求,因此,使用IntentService类实现服务也许是最好的选择。

IntentService执行以下操作:

*创建默认的工作线程,用于在应用的主线程外执行传递给onStartCommand()的所有Intent。

*创建工作队列,用于将Intent逐一传递给onHandIntent()实现,这样不必担心多线程的问题。

*在处理完所有启动请求后停止服务,故不必调用stopSelf()。

*提供onBind()的默认实现(返回null)。

*提供onStartCommand()的默认实现,可将Intent依次发送到工作队列和onHandleIntent()实现。

综上所述,只需事先onHandleIntent()来完成客户端提供的工作即可。

以下是IntentService的实现实例:

public class HelloIntentService extends IntentService {public HelloIntentService() {super("HelloIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {try {Thread.sleep(5000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

只需一个构造函数和一个onHandleIntent()实现即可。

如果还要重写其他回调方法(如onCreate(), onStartCommand(), onDestroy())确保调用超类实现,以便IntentService能够妥善处理工作线程的生命周期。

扩展服务类

使用IntentService显著简化了启动服务的实现,但是若要求服务执行多线程,而不是通过工作对联处理启动请求,则可扩展Service类来处理每个Intent。
以下是提供了Service类实现的代码,执行的工作与上述IntentService相同,级每个启动请求,均使用工作线程执行作业,且每次仅处理一个请求。

public class HelloService extends Service {private Looper mServiceLooper;private ServiceHandler mServiceHandler;private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {try {Thread.sleep(5000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}stopSelf(msg.arg1);}}@Overridepublic void onCreate() {HandlerThread thread = new HandlerThread("ServiceStartArguments",Process.THREAD_PRIORITY_BACKGROUND);thread.start();mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;mServiceHandler.sendMessage(msg);return START_STICKY;}@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onDestroy() {Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();}
}

由于是自己处理onStartCommand()的每个调用,故可以同时执行多个请求,可以为每个请求创建一个新线程,然后立即运行这些线程。注意,onStartCommand()方法必须返回整型,整型是一个值,用于描述系统应该如何在服务终止的情况下继续运行服务,返回的值必须是以下常量之一:

START_NOT_STICKY----最安全的选项

START_STICKY---适用于不执行命令但无限期运行并等待作业的媒体播放器

START_REDELIVER_INTENT---适用于主动执行应该立即恢复的作业(如:下载)

启动服务:

可以通过将Intent传递给startService(),从Activity或其他应用组件启动服务,Android系统调用onStartCommand()方法,并向其传递Intent。注意,切勿直接调用onStartCommand()。

如,Activity可以结合使用显示Intent与startService()启动服务:

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

startService()方法立即返回,且Android系统调用服务的onStartCommand()方法,如果服务尚未运行,则系统先调用onCreate(),然后调用onStartCommand()。多个服务启动请求,会导致多次对服务的onStartCommand()调用,但停止只需一次服务停止调用(stopSelf()或stopService()).

停止服务

启动服务必须管理自己的生命周期,即除非系统必须回收内存资源,否则系统不会停止或销毁服务,故服务必须通过调用stopSelf()来自行停止运行,或者另一个组件通过调用stopService()来停止。

调用stopSelf(int)传递与停止请求对应的ID服务,指定停止对应ID的服务,若stopService()会停止全部服务。

创建绑定服务

绑定服务允许应用组件通过调用bindService()与其绑定,以便创建长期连接,通常不允许组件通过调用startService()来启动。

要创建绑定服务,必须实现onBind()回调方法以但会IBinder,用于定义与服务通信的接口。然后其他Activity可以调用bindService()来检索该接口,并开始对服务调用方法,若没有组件绑定到服务,系统会自动销毁该服务。服务于客户端之间的接口必须是IBinder的实现,且服务必须从onBind()回调方法返回,一旦客户端收到IBinder,即开始通过该接口与服务进行交互。多个客户端可以同时绑定到服务,客户端完成与服务的交互后,会调用unbindService()取消绑定,一旦没有客户端与服务绑定,则系统会销毁掉服务。
向用户发送通知

服务可以使用Toast通知或状态栏通知来通知用户所发生的事件。通常,状态栏通知是最好的。

在前台运行服务

前台服务即使在内存不足时,系统也不会终止,必须在状态栏提供通知,除非服务停止或被移除,否则不能清除通知。

让服务运行在前台,需调用startForeground()采用两个参数,唯一标识通知的整型数和状态栏的Notification,例如:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

注意,startForeground()的整型ID不得为0

若要从前台移除,调用stopForeground()采用一个布尔值,指示是否也移除状态栏通知,此方法不会停止服务,但如果在服务正在前台运行时将其停止,则通知也会被移除。

管理服务生命周期:

服务的生命周期比Activity生命周期简单,但更应密切关注如何创建和销毁服务。

服务生命周期有两条路径:

启动服务:在Activity调用startService()时创建,然后无限运行,必须通过调用stopSelf()来自行停止运行。其他组件也可以调用stopService()来停止服务。服务停止后,系统将其销毁。

绑定服务:服务在客户端调用bindService()时创建,然后客户端通过IBinder接口与服务进行通信。客户端可以通过调用unbindService()关闭连接,多个客户端可以绑定到相同的服务,但所有绑定都取消后,系统自动销毁服务。

这两条路径并非完全独立,可以绑定到已经使用startService()启动的服务,例如,可以通过使用Intent调用startService()来启动后台服务,之后Activity可以通过调用bindService()绑定到服务,除非所有客户端都取消绑定,否则stopService()或stopSelf()不会停止服务。

服务生命周期的回调:

与Activity类似,可以实现服务生命周期的回调方法来监控服务状态或添加执行工作。

public class ExampleService extends Service {int mStartMode;       //表明如果服务销毁时行为IBinder mBinder;      //绑定客户端的接口boolean mAllowRebind; //表明重新绑定是否应该被绑定@Overridepublic void onCreate() {//服务被创建}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {//开始服务,因为调用了startService()方法return mStartMode;}@Overridepublic IBinder onBind(Intent intent) {//一个客户端正在调用bindService()绑定到服务return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {//全部客户端通过调用unbindService()取消绑定 return mAllowRebind;}@Overridepublic void onRebind(Intent intent) {//一个客户端正在调用bindService()绑定到服务//在onUnbind()被调用后}@Overridepublic void onDestroy() {//服务不在被使用且被销毁后}
}

服务的有效生命周期从调用onStartCommand()或onBind()开始,每种方法均由Intent对象,分为传递到startService()或bindService(),启动服务的有效生命周期与整个生命周期同时结束,绑定服务的有效生命周期在onUnbind()返回时结束。

Android服务部分总结相关推荐

  1. android从服务端获取json解析显示在客户端上面,Android服务端获取json解析显示在客户端上面.doc...

    Android服务端获取json解析显示在客户端上面 Android从服务端获取json解析显示在客户端上面 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比 ...

  2. erlang-百度云推送Android服务端功能实现-erlang

    百度云推送官方地址http://developer.baidu.com/wiki/index.php?title=docs/cplat/push 简单的介绍下原理: 百度云推送支持IOS和Androi ...

  3. Android服务一 创建启动服务

    若要学习创建绑定服务,请查看下篇Android服务二 创建绑定服务 启动服务 基于Service package service;import android.app.Service; import ...

  4. Qt创建Android服务

    Qt创建Android服务 创建Android服务 创建Android服务 从Qt 5.7开始,您可以使用Qt创建Android服务.服务是在后台运行的组件,因此它没有用户界面.执行长期操作(例如记录 ...

  5. Android 服务入门

    前言:硬着头皮把数据库SQLite看完了,接下来就是android服务了,因为自己本身就是菜鸟,所以呢,也只是做做笔记,技术上的东西就别指望我了. 1.什么是服务呢?举个例子,百度地图,美团外卖,OF ...

  6. android.os.binderproxy cannot be cast to,Android服务android.os.BinderProxy错误

    我一直在尝试使此android服务正常工作,但我不知道为什么会收到此错误. 05-13 12:13:36.203: ERROR/dalvikvm(7782): could not disable co ...

  7. android 服务自动结束,Android服务自动停止

    我正在制作一个带有闹钟功能的应用程序.我正在使用这种服务,不断检查设备的当前时间与我的数据库中的时间.Android服务自动停止 我的问题是,如果应用程序从后台删除或设备是rebooted,此serv ...

  8. Android服务函数远程调用源码分析

    在Android服务查询完整过程源码分析中介绍了客户进程向ServiceManager进程查询服务的完整过程,ServiceManager进程根据服务名称在自身维护的服务链表中查找ServiceMan ...

  9. Android服务查询完整过程源码分析

    Android服务注册完整过程源码分析中从上到下详细分析了Android系统的服务注册过程,本文同样针对AudioService服务来介绍Android服务的查询过程. 客户端进程数据发送过程 pri ...

  10. Android服务注册完整过程源码分析

    前面从不同片段分析了Android的Binder通信机制,本文结合前面介绍的内容,对整个Android的Binder通信过程进行一次完整的分析.分析以AudioService服务的注册过程为例. 由于 ...

最新文章

  1. pfSense 2.4.4-RELEASE现已发布!
  2. 云计算炒作多过采纳 普及仍需时日
  3. php代码上线,实现版本切换
  4. 【我想进大厂】Redis夺命连环11问
  5. 转网口显示未识别的网络_已有1700万用户携号转网 超99%用户1小时内办结
  6. 黑苹果2k屏_一加手机屏幕新特性:120Hz、2K+ OLED、10bit
  7. java有几大对象_一个 Java 对象到底有多大?
  8. VS2018+TensorFlow安装
  9. 夫妻宫十星所暗示的未来另一半
  10. 公司职员薪水管理系统(List)
  11. mfc将图形涂满颜色,(c++)使用顺序栈
  12. 基于 EG6831 的无感 BLDC 控制方案
  13. 【yolov5 v6.0】中断以后重新训练,增加epochs,冻结层
  14. 托福高频真词List09 // 附托福TPO阅读真题
  15. vnc远程linux命令,用VNC实现远程桌面共享(支持Windows, Linux, …) | 易水博客
  16. 浮点数二分模板---yxc
  17. 开源BBS论坛软件推荐
  18. H3C静态路由与BFD联动(单跳检测)配置案例
  19. Vue2.0面试题集合
  20. 计算机专业课程知识目标,计算机应用专业课程教学计划

热门文章

  1. instant.now时区不正确_Centos8如何更改时区
  2. jrebel热部署不起作用_5种SpringBoot热部署方式,你用哪种?
  3. pve 群晖 virtio速度慢_群晖DS Note高级教程——教你使用智能记事本
  4. rabbitmq启动方式
  5. 在公网上的Linux,我的一些配置分享
  6. 本地方法中printf如何传给java--java系统级命名管道
  7. 安装mysql 5.5.14 报错
  8. VMware Workstation三种网络连接模式说明(Bridged,NAT,Host-only networking)
  9. MAPGIS中输入分数和上下标格式的字符串。
  10. Redhat、CentOS进单用户模式进行维护