Android 学习笔记--Service

Author Avatar
ChihoPang 9月 15, 2017
  • 在其它设备中阅读本文章

Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。知识点有:清单声明、前台服务、生命周期、onStartCommand() 返回值选择、启动服务、绑定服务,思维导图已提供知识点总览。

参考资料

服务 | Android Developers

思维导图

清单声明

添加 < service > 元素作为 < application > 元素的子元素,android:name 属性是唯一必需的属性。
为了确保应用的安全性,请始终使用显式 Intent 启动或绑定 Service,且不要为服务声明 Intent 过滤器。
还可以通过添加 android:exported 属性并将其设置为 “false”,确保服务仅适用于您的应用。

前台服务

前台服务可提高服务的生存优先级,开启后在状态栏会有通知。在服务中通过 startForeground() 开启,stopForeground() 结束,具体实现代码如下。

Notification notification = new Notification(icRes, string,System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, title,message, pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

生命周期

不管启动方式如何,任何服务均有可能允许客户端与其绑定。因此,最初使用 onStartCommand()启动的服务仍可接收对 onBind() 的调用,即先通过 startService() 启动,后通过 bindService() 绑定。
服务的生命周期包含以下方法:

  • onCreate():服务正在创建
  • onStartCommand():启动服务正在 Starting
  • onBind():绑定服务正在绑定
  • onUnbind():所有服务均已通过 unbindService() 取消绑定
  • onRebind():客户端在 onUnbind() 之后绑定服务
  • onDestroy():服务销毁

onStartCommand() 返回值选择

onStartCommand() 的返回值必须是以下三者之一:

  • START_NOT_STICKY(最安全的选项)
    如果 onStartCommand() 服务被销毁且无剩余 Intent 等待处理,则一直到有新的 Intent 启动服务时,才会重新创建服务对象。
  • START_STICKY
    如果 onStartCommand() 后服务被销毁,系统会自行创建一个新的服务并传入 null intent。适用于媒体播放器等存在空作业可能性,且需要无限期运行的服务。
  • START_REDELIVER_INTENT
    如果 onStartCommand() 后服务被销毁,系统会自行创建一个新的服务并传入最后一个 Intent。适用于下载文件等应该立即恢复的服务。

启动服务

通过 startService() 使用,与启动组件无关联。启动服务在启动之后也可再被绑定。

创建 Service 子类实现启动服务

  • startService() 后会将 intent 传至 onStartCommand() 中,故应重写此方法,实现 Service 操作内容。注意 Service 默认使用主线程,需要自行创建工作线程。
  • 启动后会无限期运行,需在服务类中调用 stopSelf() 或在其他组件中调用 stopService(intent) 来停止服务运行。
  • 必须实现父类抽象方法 onBind(intent),使用绑定服务时会调用此方法,若不想实现绑定服务,可直接 return null 。

创建 IntentService 子类实现启动服务

  • 会自动创建工作线程和工作队列(源码通过 HandlerThread+Handler 实现),最终将 Intent 传至 onHandleIntent(intent),由开发者处理。
  • 处理完队列中所有 Intent 后,会自行停止服务,不必手动停止。
  • 必须实现父类抽象方法 onHandleIntent(intent) 进行 Service 操作。onBind(intent) 已默认 return null。

绑定服务

通过 bindService() 使用。绑定服务可与组件进行交互。为其他组件服务时处于活动状态,不会无限期在后台运行。

在组件中绑定服务

调用 boolean bindService (Intent service, ServiceConnection connection, int flags) 绑定服务,并在提供 ServiceConnection 匿名类对象,通过重写 connection.onServiceConnected() 获取 service.onBind() 提供的用于通信的 IBinder 。

服务端提供 IBinder

  • 若服务与组件在同一个进程中,可直接创建 Binder 子类,在子类中提供交互方法,并在 onBind() 中返回子类实例。
  • 若服务与组件不在同一个进程,则需要使用进程间通信 (IPC) 机制,具体方法包含 Messenger 和 AIDL 两种,将在 IPC 相关文章中讲解。

销毁绑定服务

组件可通过 unbindService() 从而断开绑定连接,当所有绑定连接断开后,系统即会销毁该服务。