第二板块:Android 四大组件标准化学理 | 第八篇:Service 后台执行实体与优先级

第二板块:Android 四大组件标准化学理 | 第八篇:Service 后台执行实体与优先级

所属板块:第二板块 --- Android 四大组件标准化学理

前置知识:第七篇中的 Activity 任务栈、AMS 调度、进程孵化、Binder IPC

本篇定位 :Service 是 Android 系统中唯一没有可视化界面、长期运行于后台 的组件。本篇将彻底拆解 Service 的双生性 (启动与绑定)、生命周期悖论优先级调度算法前台服务(Foreground Service)的生存法则Bound Service 的连接池模型AIDL 的 IPC 序列化机制JobScheduler 与 WorkManager 的系统级调度 。我们将深入 ActivityManagerService (AMS)ActiveServices 的源码级逻辑,揭示 Service 为何容易被杀死、以及如何正确保活(非黑科技,而是系统规范)。全程无业务代码、无最佳实践建议,仅保留 Android Framework 的底层定义与系统级调度规范。


1. 核心结论先行(Thesis Statement)

Service 是 Android 操作系统中用于在后台执行长时间运行操作 的组件。它不是线程 ,也不是进程 ,而是一个由系统服务(AMS)管理的、具有独立生命周期的、运行在应用进程中的实体

  • Service 的本质 :一个后台执行实体(Background Execution Entity)。它不提供 UI,但可以在后台播放音乐、下载文件、执行网络请求或处理数据。
  • 双生性(Duality) :Service 有两种截然不同的激活方式:启动(Started)绑定(Bound)。这两种方式决定了 Service 的生命周期和行为。
  • 优先级的核心 :Service 的生存能力取决于它在系统中的进程优先级(oom_adj)。前台服务(Foreground Service)拥有最高优先级,几乎不会被杀死;而后台服务(Background Service)极易被 Low Memory Killer 回收。
  • IPC 的桥梁:Service 是 Android 实现**进程间通信(IPC)**的主要载体。通过 Binder 和 AIDL,Service 可以向其他进程提供服务接口。

2. Service 的两种激活模式(The Two Faces of Service)

2.1 启动模式(Started Service)

当一个组件(如 Activity)调用 startService() 时,Service 被启动。它独立于启动它的组件运行,即使启动它的组件被销毁,Service 仍会继续运行。

学术定义

  • 生命周期onCreate()onStartCommand()onDestroy()
  • 独立性 :启动后,Service 与启动者无直接关联。启动者无法直接与 Service 通信(除非使用广播或 Messenger)。
  • 终止条件 :Service 必须调用 stopSelf() 或被其他组件调用 stopService() 才能停止。

示例场景

  • 后台下载文件。
  • 上传日志。
  • 同步服务器数据。

2.2 绑定模式(Bound Service)

当一个组件(如 Activity)调用 bindService() 时,Service 被绑定。它提供了一个客户端-服务器接口,允许组件与 Service 进行交互、发送请求、获取结果,甚至跨进程(IPC)通信。

学术定义

  • 生命周期onCreate()onBind()onUnbind()onDestroy()
  • 依赖性 :绑定是临时性的。当所有绑定的组件都解绑(unbind)后,Service 会自动销毁。
  • 交互性 :客户端通过 IBinder 接口与 Service 通信。

示例场景

  • 音乐播放器(Activity 控制播放/暂停)。
  • 提供数据查询接口(ContentProvider 的替代方案)。
  • 跨进程功能调用。

2.3 混合模式(Hybrid Service)

一个 Service 可以同时被启动绑定。这是最复杂的情况。

学术定义

  • 生命周期onCreate()onStartCommand()onBind()onUnbind()onRebind()onDestroy()
  • 终止条件 :必须同时满足:停止启动(stopSelf()/stopService()所有绑定者解绑(unbindService()

3. Service 生命周期拓扑学(Lifecycle Topology)

3.1 生命周期状态机(DFA)

Service 的生命周期比 Activity 简单,但混合模式下的状态转换较为复杂。
#mermaid-svg-4Sp3wflh2xDUE4dX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4Sp3wflh2xDUE4dX .error-icon{fill:#552222;}#mermaid-svg-4Sp3wflh2xDUE4dX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4Sp3wflh2xDUE4dX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4Sp3wflh2xDUE4dX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX .marker.cross{stroke:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4Sp3wflh2xDUE4dX p{margin:0;}#mermaid-svg-4Sp3wflh2xDUE4dX defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-4Sp3wflh2xDUE4dX g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-4Sp3wflh2xDUE4dX g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-4Sp3wflh2xDUE4dX g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-4Sp3wflh2xDUE4dX g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-4Sp3wflh2xDUE4dX .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-4Sp3wflh2xDUE4dX .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-4Sp3wflh2xDUE4dX .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-4Sp3wflh2xDUE4dX .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-4Sp3wflh2xDUE4dX .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-4Sp3wflh2xDUE4dX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4Sp3wflh2xDUE4dX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4Sp3wflh2xDUE4dX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4Sp3wflh2xDUE4dX .edgeLabel .label text{fill:#333;}#mermaid-svg-4Sp3wflh2xDUE4dX .label div .edgeLabel{color:#333;}#mermaid-svg-4Sp3wflh2xDUE4dX .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-4Sp3wflh2xDUE4dX .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-4Sp3wflh2xDUE4dX .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-4Sp3wflh2xDUE4dX .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX #statediagram-barbEnd{fill:#333333;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4Sp3wflh2xDUE4dX .cluster-label,#mermaid-svg-4Sp3wflh2xDUE4dX .nodeLabel{color:#131300;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-4Sp3wflh2xDUE4dX .note-edge{stroke-dasharray:5;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-note text{fill:black;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram-note .nodeLabel{color:black;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagram .edgeLabel{color:red;}#mermaid-svg-4Sp3wflh2xDUE4dX #dependencyStart,#mermaid-svg-4Sp3wflh2xDUE4dX #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-4Sp3wflh2xDUE4dX .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4Sp3wflh2xDUE4dX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} onCreate()
onStartCommand()
onBind()
onStartCommand()
onRebind()
stopSelf() / stopService()
onUnbind()
Created
Started
Bound
StartedAgain
BoundAgain
Destroyed
启动模式

独立运行
绑定模式

依赖客户端

3.2 onStartCommand() 的返回值(Redelivery Policy)

startService() 后,系统会调用 onStartCommand()。该方法返回一个整数,告诉系统在 Service 被杀死后应该如何处理。

返回值 学术定义 系统行为
START_STICKY 粘性 Service 如果 Service 被杀死,系统会尝试重新创建它,并调用 onStartCommand(),但不会传递最后的 Intent。适用于媒体播放器。
START_NOT_STICKY 非粘性 Service 如果 Service 被杀死,系统不会重新创建它,除非有新的 Intent 传入。适用于定时任务。
START_REDELIVER_INTENT 重传 Intent 如果 Service 被杀死,系统会重新创建它,并重传最后一个 Intent。适用于下载任务。

源码级解释

java 复制代码
// ActiveServices.java
private void handleServiceArgs(...) {
    int res = service.onStartCommand(args.args, flags, startId);
    if (res == Service.START_STICKY) {
        // 标记 Service 为粘性
        r.sticky = true;
    }
}

4. Service 的优先级与进程调度

4.1 进程优先级(oom_adj)体系

Service 的生存能力取决于它所在的进程优先级。AMS 根据 Service 的状态计算 oom_adj 值。

Service 状态 oom_adj 值 进程类别 被杀死概率
前台 Service 0 FOREGROUND_APP_ADJ 极低
可见 Service 1 VISIBLE_APP_ADJ
服务 Service 2 - 5 SERVICE_ADJ
缓存 Service 9 - 15 CACHED_APP_ADJ

4.2 前台服务(Foreground Service)

前台服务是 Service 的最高优先级形态。它必须在状态栏显示一个持续的通知,告知用户正在运行。

学术定义

  • 通知渠道:Android 8.0 (O) 以上,必须创建通知渠道。
  • 持续通知 :通知的 flags 必须包含 FLAG_ONGOING_EVENTFLAG_NO_CLEAR
  • 优先级 :前台 Service 的 oom_adj 为 0,与 Activity 同等级别。

代码示例(系统规范)

java 复制代码
// 在 Service 中调用
startForeground(NOTIFICATION_ID, notification);

系统限制

  • Android 8.0 (O) 引入了后台执行限制。后台 Service 无法启动前台 Service,除非应用处于前台。
  • Android 9.0 § 引入了前台服务权限FOREGROUND_SERVICE)。

5. Bound Service 与 IPC 机制

5.1 Binder 通信模型

Bound Service 的核心是 Binder IPC 。Service 返回一个 IBinder 对象,客户端通过这个对象与 Service 通信。
#mermaid-svg-cktFr4MNR1QpS87f{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cktFr4MNR1QpS87f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cktFr4MNR1QpS87f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cktFr4MNR1QpS87f .error-icon{fill:#552222;}#mermaid-svg-cktFr4MNR1QpS87f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cktFr4MNR1QpS87f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cktFr4MNR1QpS87f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cktFr4MNR1QpS87f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cktFr4MNR1QpS87f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cktFr4MNR1QpS87f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cktFr4MNR1QpS87f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cktFr4MNR1QpS87f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cktFr4MNR1QpS87f .marker.cross{stroke:#333333;}#mermaid-svg-cktFr4MNR1QpS87f svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cktFr4MNR1QpS87f p{margin:0;}#mermaid-svg-cktFr4MNR1QpS87f .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cktFr4MNR1QpS87f .cluster-label text{fill:#333;}#mermaid-svg-cktFr4MNR1QpS87f .cluster-label span{color:#333;}#mermaid-svg-cktFr4MNR1QpS87f .cluster-label span p{background-color:transparent;}#mermaid-svg-cktFr4MNR1QpS87f .label text,#mermaid-svg-cktFr4MNR1QpS87f span{fill:#333;color:#333;}#mermaid-svg-cktFr4MNR1QpS87f .node rect,#mermaid-svg-cktFr4MNR1QpS87f .node circle,#mermaid-svg-cktFr4MNR1QpS87f .node ellipse,#mermaid-svg-cktFr4MNR1QpS87f .node polygon,#mermaid-svg-cktFr4MNR1QpS87f .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cktFr4MNR1QpS87f .rough-node .label text,#mermaid-svg-cktFr4MNR1QpS87f .node .label text,#mermaid-svg-cktFr4MNR1QpS87f .image-shape .label,#mermaid-svg-cktFr4MNR1QpS87f .icon-shape .label{text-anchor:middle;}#mermaid-svg-cktFr4MNR1QpS87f .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cktFr4MNR1QpS87f .rough-node .label,#mermaid-svg-cktFr4MNR1QpS87f .node .label,#mermaid-svg-cktFr4MNR1QpS87f .image-shape .label,#mermaid-svg-cktFr4MNR1QpS87f .icon-shape .label{text-align:center;}#mermaid-svg-cktFr4MNR1QpS87f .node.clickable{cursor:pointer;}#mermaid-svg-cktFr4MNR1QpS87f .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cktFr4MNR1QpS87f .arrowheadPath{fill:#333333;}#mermaid-svg-cktFr4MNR1QpS87f .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cktFr4MNR1QpS87f .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cktFr4MNR1QpS87f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cktFr4MNR1QpS87f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cktFr4MNR1QpS87f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cktFr4MNR1QpS87f .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cktFr4MNR1QpS87f .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cktFr4MNR1QpS87f .cluster text{fill:#333;}#mermaid-svg-cktFr4MNR1QpS87f .cluster span{color:#333;}#mermaid-svg-cktFr4MNR1QpS87f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cktFr4MNR1QpS87f .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cktFr4MNR1QpS87f rect.text{fill:none;stroke-width:0;}#mermaid-svg-cktFr4MNR1QpS87f .icon-shape,#mermaid-svg-cktFr4MNR1QpS87f .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cktFr4MNR1QpS87f .icon-shape p,#mermaid-svg-cktFr4MNR1QpS87f .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cktFr4MNR1QpS87f .icon-shape .label rect,#mermaid-svg-cktFr4MNR1QpS87f .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cktFr4MNR1QpS87f .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cktFr4MNR1QpS87f .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cktFr4MNR1QpS87f :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 服务端进程
客户端进程

  1. bindService
  2. Binder IPC (transact/onTransact)
  3. 调用
    Activity/Fragment
    Binder Proxy (Stub.Proxy)
    Service
    Binder Stub (Stub)
    ServiceImpl

5.2 AIDL 的序列化机制

AIDL(Android Interface Definition Language)是 Android 的 IPC 接口定义语言。它定义了客户端和服务端通信的契约。

学术定义

  • Parcelable :AIDL 传输的对象必须实现 Parcelable 接口,以便在不同进程间序列化和反序列化。
  • Stub :服务端实现的基类,包含 onTransact() 方法,负责接收并处理客户端的请求。
  • Proxy :客户端持有的代理对象,负责将请求打包成 Parcel,发送给服务端。

AIDL 文件示例

aidl 复制代码
// IRemoteService.aidl
interface IRemoteService {
    int getPid();
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);
}

生成的 Java 代码解析

  • IRemoteService.Stub:抽象类,继承 Binder,实现 IRemoteService。服务端必须继承此类并实现接口方法。
  • IRemoteService.Stub.Proxy:客户端使用的代理类,实现 IRemoteService。它将方法调用转换为 Binder 事务。

6. Service 的启动与调度流程

6.1 startService() 的源码级流程

Service 进程 ActiveServices ActivityManagerService 应用进程 Service 进程 ActiveServices ActivityManagerService 应用进程 #mermaid-svg-gpVNukRnX62vTNEO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gpVNukRnX62vTNEO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gpVNukRnX62vTNEO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gpVNukRnX62vTNEO .error-icon{fill:#552222;}#mermaid-svg-gpVNukRnX62vTNEO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gpVNukRnX62vTNEO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gpVNukRnX62vTNEO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gpVNukRnX62vTNEO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gpVNukRnX62vTNEO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gpVNukRnX62vTNEO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gpVNukRnX62vTNEO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gpVNukRnX62vTNEO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gpVNukRnX62vTNEO .marker.cross{stroke:#333333;}#mermaid-svg-gpVNukRnX62vTNEO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gpVNukRnX62vTNEO p{margin:0;}#mermaid-svg-gpVNukRnX62vTNEO .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gpVNukRnX62vTNEO text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-gpVNukRnX62vTNEO .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gpVNukRnX62vTNEO .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-gpVNukRnX62vTNEO .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-gpVNukRnX62vTNEO .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-gpVNukRnX62vTNEO #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-gpVNukRnX62vTNEO .sequenceNumber{fill:white;}#mermaid-svg-gpVNukRnX62vTNEO #sequencenumber{fill:#333;}#mermaid-svg-gpVNukRnX62vTNEO #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-gpVNukRnX62vTNEO .messageText{fill:#333;stroke:none;}#mermaid-svg-gpVNukRnX62vTNEO .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gpVNukRnX62vTNEO .labelText,#mermaid-svg-gpVNukRnX62vTNEO .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-gpVNukRnX62vTNEO .loopText,#mermaid-svg-gpVNukRnX62vTNEO .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-gpVNukRnX62vTNEO .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gpVNukRnX62vTNEO .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-gpVNukRnX62vTNEO .noteText,#mermaid-svg-gpVNukRnX62vTNEO .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-gpVNukRnX62vTNEO .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gpVNukRnX62vTNEO .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gpVNukRnX62vTNEO .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gpVNukRnX62vTNEO .actorPopupMenu{position:absolute;}#mermaid-svg-gpVNukRnX62vTNEO .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-gpVNukRnX62vTNEO .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gpVNukRnX62vTNEO .actor-man circle,#mermaid-svg-gpVNukRnX62vTNEO line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-gpVNukRnX62vTNEO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} altService 未运行 startService(intent)startServiceLocked()查找 ServiceRecordbringUpServiceLocked()创建进程 (fork)onCreate()sendServiceArgsLocked()onStartCommand()

关键数据结构

  • ServiceRecord :AMS 中保存 Service 信息的记录,包含 nameprocessNameintentFilter 等。
  • ServiceMap:AMS 中按用户 ID 存储的 Service 映射表。

6.2 bindService() 的源码级流程

Service 进程 ActiveServices ActivityManagerService 应用进程 Service 进程 ActiveServices ActivityManagerService 应用进程 #mermaid-svg-brvRYIGaayXSE2dj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-brvRYIGaayXSE2dj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-brvRYIGaayXSE2dj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-brvRYIGaayXSE2dj .error-icon{fill:#552222;}#mermaid-svg-brvRYIGaayXSE2dj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-brvRYIGaayXSE2dj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-brvRYIGaayXSE2dj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-brvRYIGaayXSE2dj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-brvRYIGaayXSE2dj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-brvRYIGaayXSE2dj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-brvRYIGaayXSE2dj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-brvRYIGaayXSE2dj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-brvRYIGaayXSE2dj .marker.cross{stroke:#333333;}#mermaid-svg-brvRYIGaayXSE2dj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-brvRYIGaayXSE2dj p{margin:0;}#mermaid-svg-brvRYIGaayXSE2dj .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-brvRYIGaayXSE2dj text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-brvRYIGaayXSE2dj .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-brvRYIGaayXSE2dj .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-brvRYIGaayXSE2dj .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-brvRYIGaayXSE2dj .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-brvRYIGaayXSE2dj #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-brvRYIGaayXSE2dj .sequenceNumber{fill:white;}#mermaid-svg-brvRYIGaayXSE2dj #sequencenumber{fill:#333;}#mermaid-svg-brvRYIGaayXSE2dj #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-brvRYIGaayXSE2dj .messageText{fill:#333;stroke:none;}#mermaid-svg-brvRYIGaayXSE2dj .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-brvRYIGaayXSE2dj .labelText,#mermaid-svg-brvRYIGaayXSE2dj .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-brvRYIGaayXSE2dj .loopText,#mermaid-svg-brvRYIGaayXSE2dj .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-brvRYIGaayXSE2dj .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-brvRYIGaayXSE2dj .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-brvRYIGaayXSE2dj .noteText,#mermaid-svg-brvRYIGaayXSE2dj .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-brvRYIGaayXSE2dj .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-brvRYIGaayXSE2dj .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-brvRYIGaayXSE2dj .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-brvRYIGaayXSE2dj .actorPopupMenu{position:absolute;}#mermaid-svg-brvRYIGaayXSE2dj .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-brvRYIGaayXSE2dj .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-brvRYIGaayXSE2dj .actor-man circle,#mermaid-svg-brvRYIGaayXSE2dj line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-brvRYIGaayXSE2dj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} altService 未运行 bindService(intent, conn, flags)bindServiceLocked()查找 ServiceRecordbringUpServiceLocked()创建进程 (fork)onCreate()requestServiceBindingsLocked()onBind()返回 IBinderonServiceConnected(conn, binder)


7. Service 的销毁与回收

7.1 销毁流程

Service 的销毁由 AMS 统一管理。
Service 进程 ActiveServices ActivityManagerService 应用进程 Service 进程 ActiveServices ActivityManagerService 应用进程 #mermaid-svg-4UmOi4kEVPD0v8jv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4UmOi4kEVPD0v8jv .error-icon{fill:#552222;}#mermaid-svg-4UmOi4kEVPD0v8jv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4UmOi4kEVPD0v8jv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4UmOi4kEVPD0v8jv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4UmOi4kEVPD0v8jv .marker.cross{stroke:#333333;}#mermaid-svg-4UmOi4kEVPD0v8jv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4UmOi4kEVPD0v8jv p{margin:0;}#mermaid-svg-4UmOi4kEVPD0v8jv .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4UmOi4kEVPD0v8jv text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-4UmOi4kEVPD0v8jv .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-4UmOi4kEVPD0v8jv .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-4UmOi4kEVPD0v8jv #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-4UmOi4kEVPD0v8jv .sequenceNumber{fill:white;}#mermaid-svg-4UmOi4kEVPD0v8jv #sequencenumber{fill:#333;}#mermaid-svg-4UmOi4kEVPD0v8jv #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-4UmOi4kEVPD0v8jv .messageText{fill:#333;stroke:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4UmOi4kEVPD0v8jv .labelText,#mermaid-svg-4UmOi4kEVPD0v8jv .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .loopText,#mermaid-svg-4UmOi4kEVPD0v8jv .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-4UmOi4kEVPD0v8jv .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-4UmOi4kEVPD0v8jv .noteText,#mermaid-svg-4UmOi4kEVPD0v8jv .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-4UmOi4kEVPD0v8jv .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4UmOi4kEVPD0v8jv .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4UmOi4kEVPD0v8jv .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-4UmOi4kEVPD0v8jv .actorPopupMenu{position:absolute;}#mermaid-svg-4UmOi4kEVPD0v8jv .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-4UmOi4kEVPD0v8jv .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-4UmOi4kEVPD0v8jv .actor-man circle,#mermaid-svg-4UmOi4kEVPD0v8jv line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-4UmOi4kEVPD0v8jv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} alt引用计数为 0 stopService() / unbindService()stopServiceLocked() / unbindServiceLocked()检查引用计数scheduleStopService()onDestroy()serviceDoneExecuting()更新进程优先级

7.2 低内存回收(Low Memory Killer)

当系统内存不足时,LMK 会根据 Service 的优先级进行回收。

回收策略

  1. 优先回收 :处于后台的 Service(oom_adj >= 9)。
  2. 其次回收 :正在运行但不在前台的 Service(oom_adj = 2-5)。
  3. 最后回收 :前台 Service(oom_adj = 0)。

学术定义

  • Service 重启 :如果 Service 返回 START_STICKY,系统会在内存充足时重新创建它。
  • Service 不重启 :如果 Service 返回 START_NOT_STICKY,系统不会重新创建它。

8. 系统级 Service 调度器(JobScheduler & WorkManager)

8.1 JobScheduler

Android 5.0 (L) 引入了 JobScheduler,用于在满足特定条件(如充电、网络连接、空闲)时执行后台任务。

学术定义

  • 条件约束:Job 可以设置网络类型、充电状态、设备空闲、电池电量等约束。
  • 批量执行:系统会将多个 Job 批量执行,以节省电量。
  • 省电机制:JobScheduler 是 Android 系统推荐的省电后台执行方案。

示例

java 复制代码
JobInfo jobInfo = new JobInfo.Builder(JOB_ID, componentName)
        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
        .setRequiresCharging(true)
        .build();
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);

8.2 WorkManager

Android Jetpack 组件,基于 JobSchedulerAlarmManagerBroadcastReceiver 构建,提供更高级的后台任务管理。

学术定义

  • 向后兼容:支持 Android 4.0+。
  • 链式任务:可以定义任务的执行顺序。
  • 保证执行:即使在应用退出或设备重启后,任务也会被执行(取决于约束条件)。

9. Service 的安全机制

9.1 权限保护

Service 可以通过权限保护,防止未授权的应用启动或绑定。

xml 复制代码
<service
    android:name=".MyService"
    android:permission="com.example.permission.MY_SERVICE" />

学术定义

  • 自定义权限:应用可以定义自己的权限,并在 Manifest 中声明。
  • 系统权限:某些系统 Service 需要特定的系统权限才能访问。

9.2 导出控制

xml 复制代码
<service
    android:name=".PublicService"
    android:exported="true" />
<service
    android:name=".PrivateService"
    android:exported="false" />

学术定义

  • exported="true":允许其他应用访问。
  • exported="false":仅限应用内部访问,防止组件暴露漏洞。

10. 关键数据结构与源码定义

10.1 ServiceRecord(AMS 中的 Service 记录)

java 复制代码
// com.android.server.am.ServiceRecord
class ServiceRecord extends Binder {
    final ServiceInfo serviceInfo;       // Manifest 信息
    final String packageName;
    final String processName;           // 运行进程
    final Intent.FilterComparison filter; // Intent 过滤器
    final ArrayMap<IBinder, ConnectionRecord> connections; // 绑定连接记录
    boolean foreground;                 // 是否为前台服务
    int lastStartId;                    // 最后一次启动 ID
}

10.2 ConnectionRecord(绑定连接记录)

java 复制代码
// com.android.server.am.ConnectionRecord
class ConnectionRecord {
    final IBinder binding;              // Binder 对象
    final IServiceConnection conn;      // 客户端连接接口
    final int flags;                    // 绑定标志
    final int clientUid;                // 客户端 UID
    final String clientProcessName;     // 客户端进程名
}

11. 本篇总结(Knowledge Closure)

关键点 纯学术定义
Service 的本质 由 AMS 管理的后台执行实体,无 UI,用于执行长时间运行的操作。
双生性 启动模式(独立运行)和绑定模式(交互运行)是 Service 的两种激活方式。
优先级 前台服务(Foreground Service)拥有最高优先级,后台服务极易被回收。
IPC 机制 通过 Binder 和 AIDL 实现跨进程通信,Service 作为服务端提供接口。
系统调度 JobScheduler 和 WorkManager 是系统推荐的后台任务调度方案,用于省电和优化性能。
安全机制 通过权限保护和导出控制,防止未授权的访问。

下一篇预告第二板块:Android 四大组件标准化学理 | 第九篇:BroadcastReceiver 事件分发与有序广播

相关推荐
会Tk矩阵群控的小木1 小时前
安卓群控系统对于游戏工作室实战教程
android·运维·游戏·adb·开源软件·个人开发
qeen872 小时前
【C++】类与对象之类的默认成员函数(二)
android·c语言·开发语言·c++·笔记·学习
故渊at2 小时前
第二板块:Android 四大组件标准化学理 | 第九篇:BroadcastReceiver 事件分发与有序广播
android·gitee·broadcast·广播·动态注册·静态注册
JohnnyDeng943 小时前
【Android】Room 数据库高级用法与性能调优:从查询瓶颈到毫秒级响应
android·性能优化·kotlin·room
zeqinjie3 小时前
Flutter 折叠屏 iPad / 宽屏适配实践
android·前端·flutter
ab_dg_dp3 小时前
Android 17+ 提取 AIDL 生成 Java 文件的实用脚本
android·java·python
Arrom4 小时前
DLNA 渲染端排障实战:从 20s 卡顿到 stale subscriber 的两周追凶之旅
android·java
_李小白4 小时前
【android opencv学习笔记】Day 32:直线检测之霍夫变换
android·opencv·学习