Android 15 Service 源码解析
基于 AOSP Android 15 源码分析
目录
- 概述
- Service架构总览
- startService启动流程
- bindService绑定流程
- Service生命周期管理
- [前台服务(Foreground Service)](#前台服务(Foreground Service))
- Binder通信机制
- 应用层使用指南
- 关键类与接口
- 最佳实践与注意事项
1. 概述
1.1 Service是什么
Service是Android四大组件之一,用于在后台执行长时间运行的操作,不提供用户界面。Service有两种工作模式:
- Started Service (启动服务) : 通过
startService()启动,独立运行,直到被主动停止 - Bound Service (绑定服务) : 通过
bindService()绑定,提供客户端-服务器接口,允许组件与之交互
1.2 核心特性
- 运行在主线程(Main Thread),不是独立进程或线程
- 可以在后台执行长时间运行的操作
- 可以为其他应用提供服务(通过导出)
- 生命周期独立于启动它的组件
1.3 关键源码文件路径
应用层 (Application Layer):
├── frameworks/base/core/java/android/app/Service.java
├── frameworks/base/core/java/android/app/ContextImpl.java
└── frameworks/base/core/java/android/content/Context.java
Framework层 (Framework Layer):
├── frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
├── frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
├── frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java
└── frameworks/base/core/java/android/app/ActivityThread.java
AIDL接口:
└── frameworks/base/core/java/android/app/IActivityManager.aidl
Native层:
└── frameworks/base/core/jni/android_util_Binder.cpp
2. Service架构总览
2.1 架构分层图
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Activity │ │ Service │ │ Context │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┴──────────────────┘ │
│ │ │
│ ContextImpl │
│ │ │
└───────────────────────────┼──────────────────────────────────┘
│ Binder IPC
┌───────────────────────────┼──────────────────────────────────┐
│ Framework Layer (System Server) │
│ │ │
│ ActivityManagerService │
│ │ │
│ ActiveServices │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ ServiceRecord ServiceMap ProcessRecord │
│ │
└───────────────────────────┼──────────────────────────────────┘
│
┌───────────────────────────┼──────────────────────────────────┐
│ Application Process │
│ │ │
│ ActivityThread │
│ │ │
│ ApplicationThread (Binder) │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ handleCreateService handleBindService handleServiceArgs │
│ │
└──────────────────────────────────────────────────────────────┘
2.2 核心组件说明
| 组件名称 | 层级 | 作用 |
|---|---|---|
Service |
应用层 | Service基类,开发者继承实现业务逻辑 |
ContextImpl |
应用层 | Context接口实现,提供startService/bindService入口 |
ActivityManagerService |
Framework层 | 系统服务,管理所有Activity和Service |
ActiveServices |
Framework层 | Service管理核心类,处理启动/绑定/停止逻辑 |
ServiceRecord |
Framework层 | 代表一个Service实例的数据结构 |
ActivityThread |
应用进程 | 应用主线程,负责Service生命周期回调 |
ApplicationThread |
应用进程 | Binder对象,接收系统服务的跨进程调用 |
3. startService启动流程
3.1 完整调用链
应用进程 System Server进程
│ │
├─ ContextImpl.startService() │
│ │ │
│ ├─ startServiceCommon() │
│ │ │ │
│ │ └─ validateServiceIntent() │
│ │ │
│ └─ ActivityManager.getService() │
│ .startService() ─────────────>│
│ [Binder IPC]│
│ │
│ ActivityManagerService.startService()
│ │
│ ActiveServices.startServiceLocked()
│ │
│ ├─ retrieveServiceLocked() (查找/创建ServiceRecord)
│ │
│ ├─ startServiceInnerLocked()
│ │
│ └─ bringUpServiceLocked()
│ │
│ ├─ 检查进程是否存在
│ │
│ ├─ realStartServiceLocked()
│ │ │
│ │ └─ app.thread.scheduleCreateService()
│<─────────────────────────────────────────────┘ [Binder IPC]
│
ActivityThread.H.handleMessage(CREATE_SERVICE)
│
├─ handleCreateService()
│ │
│ ├─ ClassLoader.loadClass(Service类)
│ │
│ ├─ service.attach(context, ...)
│ │
│ ├─ service.onCreate() ──┐
│ │ │【开发者回调】
│ └─ mServices.put(token, service)
│
└─ app.thread.scheduleServiceArgs()
│
└─ handleServiceArgs()
│
└─ service.onStartCommand() ──┐
│【开发者回调】
3.2 关键方法详解
3.2.1 应用层入口: ContextImpl.startService()
文件位置 : frameworks/base/core/java/android/app/ContextImpl.java
java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
@Override
public ComponentName startForegroundService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, true, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
// 1. 验证Intent必须是显式Intent (Android 5.0+)
validateServiceIntent(service);
// 2. 准备跨进程传递
service.prepareToLeaveProcess(this);
// 3. 通过Binder调用AMS
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), // 应用进程的Binder代理
service, // Service Intent
service.resolveTypeIfNeeded(getContentResolver()),
requireForeground, // 是否为前台服务
getOpPackageName(), // 调用包名
getAttributionTag(),
user.getIdentifier());
// 4. 记录前台服务启动堆栈(用于超时异常定位)
if (cn != null && requireForeground) {
if (cn.getPackageName().equals(getOpPackageName())) {
Service.setStartForegroundServiceStackTrace(cn.getClassName(),
new StackTrace("Last startServiceCommon() call"));
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
关键点:
- Android 5.0+ 必须使用显式Intent启动服务
requireForeground参数区分普通启动和前台服务启动- 通过Binder IPC调用系统服务AMS
3.2.2 Framework层核心: ActiveServices.startServiceLocked()
文件位置 : frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
ComponentName startServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int callingPid, int callingUid, boolean fgRequired,
String callingPackage, String callingFeatureId, final int userId,
BackgroundStartPrivileges backgroundStartPrivileges,
boolean isSdkSandboxService, int sdkSandboxClientAppUid,
String sdkSandboxClientAppPackage, String instanceName)
throws TransactionTooLargeException {
// 1. 获取调用者进程信息
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mAm.getRecordForAppLOSP(caller);
}
// 2. 解析Service信息(从PackageManager查询)
ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
resolvedType, callingPackage, callingPid, callingUid, userId,
true, callerFg, false, null, false);
ServiceRecord r = res.record;
// 3. 权限检查
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
callingFeatureId, callingUid, service, callerFg, userId, false)) {
return null;
}
// 4. 前台服务后台启动限制检查 (Android 12+)
if (fgRequired) {
// 检查是否有权限从后台启动前台服务
// 涉及多种豁免场景: TOP进程、系统UID、SYSTEM_ALERT_WINDOW权限等
int allowReason = shouldAllowFgsStartForegroundWithBindingCheckLocked(...);
if (allowReason < REASON_DENIED) {
// 允许启动前台服务
} else {
// 抛出ForegroundServiceStartNotAllowedException
}
}
// 5. 记录Service启动信息
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.pendingStarts.add(new ServiceRecord.StartItem(r, ...));
// 6. 启动Service
String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
false, false, false, true);
return r.name;
}
3.2.3 Service进程启动: ActiveServices.bringUpServiceLocked()
java
private String bringUpServiceInnerLocked(ServiceRecord r, int intentFlags,
boolean execInFg, boolean whileRestarting,
boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj, int serviceBindingOomAdjPolicy)
throws TransactionTooLargeException {
// 1. 检查Service所在进程是否已启动
final String procName = r.processName;
ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
if (app != null && app.getThread() != null) {
try {
// 进程已存在,直接启动Service
realStartServiceLocked(r, app, execInFg, enqueueOomAdj,
serviceBindingOomAdjPolicy);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
} else {
// 2. 进程不存在,先启动进程
if (app == null && !permissionsReviewRequired && !packageFrozen) {
app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated);
if (app == null) {
String msg = "Unable to launch app " + r.appInfo.packageName;
Slog.w(TAG, msg);
bringDownServiceLocked(r, enqueueOomAdj);
return msg;
}
}
}
// 3. 进程启动后会回调到realStartServiceLocked
return null;
}
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
boolean execInFg, boolean enqueueOomAdj, int serviceBindingOomAdjPolicy)
throws RemoteException {
// 1. 创建Service启动数据
final boolean newService = app.getThread() != null;
r.setProcess(app, app.getThread(), app.getPid(), app.info.uid);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
// 2. 通过Binder调用应用进程创建Service
boolean created = false;
try {
// 发送CREATE_SERVICE消息到应用进程
app.getThread().scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.mState.getReportedProcState());
created = true;
} finally {
if (!created) {
app.mServices.stopService(r);
r.setProcess(null, null, 0, 0);
}
}
// 3. 发送START指令
sendServiceArgsLocked(r, execInFg, true);
}
3.2.4 应用进程处理: ActivityThread.handleCreateService()
文件位置 : frameworks/base/core/java/android/app/ActivityThread.java
java
private void handleCreateService(CreateServiceData data) {
// 1. 取消GC调度
unscheduleGcIdler();
// 2. 获取LoadedApk
final LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo);
Service service = null;
try {
// 3. 创建Application对象(如果不存在)
Application app = packageInfo.makeApplicationInner(false, mInstrumentation);
// 4. 通过ClassLoader加载Service类
ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// 5. 创建ContextImpl
ContextImpl context = ContextImpl.getImpl(
packageInfo.makeApplication(false, mInstrumentation)
.getBaseContext());
context.setOuterContext(service);
// 6. attach Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 7. 调用onCreate()生命周期
service.onCreate();
// 8. 缓存Service实例
mServices.put(data.token, service);
mServicesData.put(data.token, data);
// 9. 通知AMS Service已创建
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name + ": " + e.toString(), e);
}
}
}
private void handleServiceArgs(ServiceArgsData data) {
CreateServiceData createData = mServicesData.get(data.token);
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess(...);
}
// 调用onStartCommand()
int res = s.onStartCommand(data.args, data.flags, data.startId);
// 根据返回值决定重启策略
// START_STICKY: 重启并传递null Intent
// START_NOT_STICKY: 不重启
// START_REDELIVER_INTENT: 重启并重新传递Intent
// 通知AMS执行完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START,
data.startId, res);
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(...);
}
}
}
}
3.3 startService流程图
Service实例 应用进程 (ActivityThread) ActiveServices System Server (ActivityManagerService) 应用进程 (ContextImpl) Service实例 应用进程 (ActivityThread) ActiveServices System Server (ActivityManagerService) 应用进程 (ContextImpl) alt [进程不存在] startService(intent) validateServiceIntent() [Binder] startService() startServiceLocked() retrieveServiceLocked() (查询PMS获取ServiceInfo) 权限检查 前台服务限制检查 bringUpServiceLocked() startProcessLocked() 启动Zygote fork进程 进程已启动 realStartServiceLocked() [Binder] scheduleCreateService() H.handleMessage(CREATE_SERVICE) handleCreateService() new Service() attach(context) onCreate() [Binder] serviceDoneExecuting() [Binder] scheduleServiceArgs() handleServiceArgs() onStartCommand(intent) return START_STICKY/NOT_STICKY [Binder] serviceDoneExecuting()
3.4 关键状态流转
ServiceRecord状态机:
┌─────────────┐
│ STOPPED │ (初始状态)
└──────┬──────┘
│ startServiceLocked()
▼
┌─────────────┐
│ STARTING │ (bringUpServiceLocked)
└──────┬──────┘
│ realStartServiceLocked()
▼
┌─────────────┐
│ CREATING │ (scheduleCreateService已发送)
└──────┬──────┘
│ onCreate()完成
▼
┌─────────────┐
│ STARTED │ (onStartCommand已调用)
└──────┬──────┘
│
│ stopService() / stopSelf()
▼
┌─────────────┐
│ STOPPING │
└──────┬──────┘
│ onDestroy()完成
▼
┌─────────────┐
│ STOPPED │
└─────────────┘
4. bindService绑定流程
4.1 完整调用链
应用进程 System Server进程
│ │
├─ ContextImpl.bindService() │
│ │ │
│ ├─ bindServiceCommon() │
│ │ │ │
│ │ ├─ validateServiceIntent() │
│ │ │ │
│ │ ├─ LoadedApk.getServiceDispatcher()
│ │ │ │ │
│ │ │ └─ 创建ServiceConnection包装为IServiceConnection
│ │ │ │
│ │ └─ ActivityManager.getService()
│ │ .bindServiceInstance() ──────>│
│ [Binder IPC]│
│ │
│ ActivityManagerService.bindServiceInstance()
│ │
│ ActiveServices.bindServiceLocked()
│ │
│ ├─ retrieveServiceLocked()
│ │
│ ├─ 创建ConnectionRecord
│ │
│ └─ bringUpServiceLocked()
│ │
│ └─ realStartServiceLocked()
│ │
│ └─ requestServiceBindingLocked()
│ │
│<─────────────────────────────────────────────────┘
│ app.thread.scheduleBindService()
│
ActivityThread.H.handleMessage(BIND_SERVICE)
│
├─ handleBindService()
│ │
│ └─ service.onBind(intent) ──┐
│ │ │【开发者回调】
│ └─ 返回IBinder对象
│
├─ publishService() [Binder IPC] ────────────>│
│ │
│ ActiveServices.publishServiceLocked()
│ │
│ ├─ 缓存IBinder
│ │
│<─────────────────────────────────┴─ connection.connected(service, binder)
│ [Binder IPC]
│
ServiceDispatcher.InnerConnection.connected()
│
└─ ServiceConnection.onServiceConnected() ──┐
│【开发者回调】
4.2 关键方法详解
4.2.1 应用层入口: ContextImpl.bindService()
文件位置 : frameworks/base/core/java/android/app/ContextImpl.java
java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, Integer.toUnsignedLong(flags),
null, mMainThread.getHandler(), null, getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn,
long flags, String instanceName, Handler handler, Executor executor,
UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
if (executor != null) {
// 使用Executor执行回调
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
executor, flags);
} else {
// 使用Handler执行回调
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
handler, flags);
}
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
// 通过Binder调用AMS
int res = ActivityManager.getService().bindServiceInstance(
mMainThread.getApplicationThread(),
getActivityToken(),
service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, // IServiceConnection (Binder对象)
flags,
instanceName,
getOpPackageName(),
user.getIdentifier());
if (res < 0) {
throw new SecurityException("Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
关键点:
ServiceConnection被包装为IServiceConnection(Binder对象)- 支持通过
Handler或Executor指定回调线程 - 返回值表示绑定是否成功
4.2.2 ServiceConnection包装: LoadedApk.ServiceDispatcher
文件位置 : frameworks/base/core/java/android/app/LoadedApk.java
java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Executor executor, int flags) {
return getServiceDispatcherCommon(c, context, null, executor, flags);
}
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
Context context, Handler handler, Executor executor, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map =
mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
// 创建新的ServiceDispatcher
if (executor != null) {
sd = new ServiceDispatcher(c, context, executor, flags);
} else {
sd = new ServiceDispatcher(c, context, handler, flags);
}
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
// 已存在,检查Context是否一致
sd.validate(context, handler, executor);
}
return sd.getIServiceConnection();
}
}
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
private final Context mContext;
private final Handler mActivityThread;
private final Executor mActivityExecutor;
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service,
boolean dead) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
}
}
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
// 连接建立
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
// 连接断开
doDeath(mName, mService);
}
}
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
synchronized (this) {
if (mConnection != null && !mDead) {
if (service != null) {
// 回调onServiceConnected
mConnection.onServiceConnected(name, service);
} else {
mConnection.onNullBinding(name);
}
}
}
}
}
关键机制:
InnerConnection是Binder对象,接收来自SystemServer的回调- 使用
WeakReference避免内存泄漏 - 通过
Handler或Executor将回调切换到指定线程
4.2.3 Framework层处理: ActiveServices.bindServiceLocked()
文件位置 : frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, long flags,
String instanceName, boolean isSdkSandboxService, ...) {
// 1. 获取调用者进程
final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);
// 2. 获取调用者Activity Token (如果从Activity调用)
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
}
// 3. 查找或创建ServiceRecord
ServiceLookupResult res = retrieveServiceLocked(service, ...);
ServiceRecord s = res.record;
// 4. 权限检查
if (!requestStartTargetPermissionsReviewIfNeededLocked(...)) {
return 0;
}
// 5. 创建ConnectionRecord
ConnectionRecord c = new ConnectionRecord(activity, connection, flags,
clientLabel, clientIntent, callerApp, s);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
// 6. 将连接添加到ServiceRecord
s.addConnection(binder, c);
// 7. 如果设置了BIND_AUTO_CREATE标志,启动Service
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired, packageFrozen, true) != null) {
mAm.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_BIND_SERVICE);
return 0;
}
}
// 8. 如果Service已运行且已绑定过,直接发布
if (s.app != null && b.intent.received) {
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Exception thrown when connected", e);
}
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
return 1;
}
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean execInFg, boolean rebind)
throws TransactionTooLargeException {
if (r.app == null || r.app.getThread() == null) {
// Service进程已死亡
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
// 调用应用进程执行onBind
r.app.getThread().scheduleBindService(r, i.intent.getIntent(),
rebind, r.app.mState.getReportedProcState());
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
return false;
}
}
return true;
}
4.2.4 应用进程处理: ActivityThread.handleBindService()
java
private void handleBindService(BindServiceData data) {
CreateServiceData createData = mServicesData.get(data.token);
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess(...);
try {
if (!data.rebind) {
// 首次绑定,调用onBind
IBinder binder = s.onBind(data.intent);
// 发布Binder对象到AMS
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
// 重新绑定,调用onRebind
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(...);
}
}
}
}
4.2.5 发布Binder: ActiveServices.publishServiceLocked()
java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (r != null) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections =
r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
continue;
}
try {
// 通过Binder回调客户端的ServiceConnection
c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
}
}
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
4.3 bindService流程图
Service实例 应用进程 (Service进程) System Server (ActiveServices) ServiceDispatcher 应用进程 (Client) Service实例 应用进程 (Service进程) System Server (ActiveServices) ServiceDispatcher 应用进程 (Client) alt [BIND_AUTO_CREATE && Service未运行] 客户端可通过IBinder与Service通信 bindService(intent, conn, flags) getServiceDispatcher() (包装ServiceConnection) IServiceConnection (Binder) [Binder] bindServiceInstance() bindServiceLocked() retrieveServiceLocked() 创建ConnectionRecord bringUpServiceLocked() onCreate() [Binder] scheduleBindService() handleBindService() onBind(intent) return IBinder [Binder] publishService(binder) publishServiceLocked() 缓存IBinder [Binder] connected(name, binder) post到Handler/Executor onServiceConnected(name, binder)
4.4 绑定标志说明
| 标志 | 值 | 说明 |
|---|---|---|
BIND_AUTO_CREATE |
0x0001 | 自动创建Service(如果不存在) |
BIND_DEBUG_UNBIND |
0x0002 | 调试模式,记录unbind调用栈 |
BIND_NOT_FOREGROUND |
0x0004 | 不提升Service进程优先级到前台 |
BIND_ABOVE_CLIENT |
0x0008 | Service进程优先级高于客户端 |
BIND_ALLOW_OOM_MANAGEMENT |
0x0010 | 允许Service进程被OOM Killer杀死 |
BIND_WAIVE_PRIORITY |
0x0020 | 不传递客户端优先级给Service |
BIND_IMPORTANT |
0x0040 | Service对客户端很重要 |
BIND_ADJUST_WITH_ACTIVITY |
0x0080 | 根据Activity可见性调整Service优先级 |
BIND_EXTERNAL_SERVICE |
0x80000000 | 绑定到外部Service (跨用户) |
5. Service生命周期管理
5.1 生命周期方法
java
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
/**
* 创建时调用 (仅调用一次)
* 用于初始化资源,创建线程等
*/
public void onCreate() {
}
/**
* START模式: 每次startService()都会调用
* @param intent 启动Intent
* @param flags 额外标志 (如START_FLAG_REDELIVERY)
* @param startId 启动ID,用于stopSelf(int)
* @return 重启策略: START_STICKY/START_NOT_STICKY/START_REDELIVER_INTENT
*/
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
/**
* BIND模式: 首次bindService()时调用
* @param intent 绑定Intent
* @return IBinder对象,客户端用于通信
*/
@Nullable
public abstract IBinder onBind(Intent intent);
/**
* BIND模式: 所有客户端unbind后,再次bind时调用
* (仅当onUnbind返回true时才会调用)
*/
public void onRebind(Intent intent) {
}
/**
* BIND模式: 所有客户端都unbind时调用
* @return true表示希望接收onRebind,false表示不需要
*/
public boolean onUnbind(Intent intent) {
return false;
}
/**
* 配置变更时调用
*/
public void onConfigurationChanged(Configuration newConfig) {
}
/**
* 低内存警告
*/
public void onLowMemory() {
}
/**
* 内存级别变化
*/
public void onTrimMemory(int level) {
}
/**
* 销毁时调用
* 释放所有资源,停止线程
*/
public void onDestroy() {
}
/**
* 停止Service (按startId)
* 只有当startId是最后一次startService的ID时才会停止
*/
public final boolean stopSelfResult(int startId) {
if (mActivityManager == null) {
return false;
}
try {
return mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
return false;
}
}
5.2 生命周期场景
场景1: Started Service生命周期
startService()
│
├─> onCreate() (首次创建)
│
├─> onStartCommand() (每次start都调用)
│
├─> onStartCommand() (再次start)
│
└─> stopService() / stopSelf()
│
└─> onDestroy()
场景2: Bound Service生命周期
bindService()
│
├─> onCreate() (首次创建)
│
├─> onBind() (首次bind)
│
└─> [Service运行中]
│
├─> unbindService()
│ │
│ └─> onUnbind() (所有客户端unbind)
│
├─> bindService()
│ │
│ └─> onRebind() (如果onUnbind返回true)
│
└─> unbindService()
│
└─> onDestroy()
场景3: 混合模式 (Started + Bound)
startService()
│
├─> onCreate()
│
├─> onStartCommand()
│
└─> bindService()
│
├─> onBind()
│
└─> [Service运行中]
│
├─> unbindService()
│ │
│ └─> onUnbind() (但Service不销毁)
│
└─> stopService()
│
└─> onDestroy()
关键规则:
- Service同时支持START和BIND两种模式
- 只有既没有START也没有BIND时才会销毁
stopService()不会立即销毁有客户端绑定的ServiceunbindService()不会销毁通过startService()启动的Service
5.3 onStartCommand返回值详解
| 返回值 | 说明 | 使用场景 |
|---|---|---|
START_STICKY (1) |
Service被杀后自动重启,Intent为null | 音乐播放器(不关心Intent) |
START_NOT_STICKY (2) |
Service被杀后不重启 | 定期同步任务(完成后无需重启) |
START_REDELIVER_INTENT (3) |
Service被杀后重启,重新传递最后的Intent | 下载任务(需要恢复Intent信息) |
START_STICKY_COMPATIBILITY (0) |
兼容模式,Android 2.0之前的行为 | 不推荐使用 |
代码示例:
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
// START_STICKY重启后intent为null
Log.w(TAG, "Service restarted with null intent");
return START_STICKY;
}
String action = intent.getAction();
if ("DOWNLOAD".equals(action)) {
String url = intent.getStringExtra("url");
startDownload(url, startId);
return START_REDELIVER_INTENT; // 下载任务需要恢复
} else {
return START_NOT_STICKY; // 一次性任务
}
}
5.4 Service重启机制
文件位置 : frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
private final void scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {
boolean canceled = false;
if (mAm.mAtmInternal.isShuttingDown()) {
// 系统关闭中,不重启
return;
}
// 计算重启延迟 (指数退避算法)
final long now = SystemClock.uptimeMillis();
final long minDuration = SERVICE_RESTART_DURATION;
final long resetTime = SERVICE_RESET_RUN_DURATION;
// 如果Service长时间运行后崩溃,重置退避时间
if (r.restartDelay == 0 ||
now > (r.restartTime + resetTime)) {
r.restartCount = 1;
r.restartDelay = minDuration;
} else {
r.restartCount++;
// 指数退避: delay = min(delay * 2, MAX_DELAY)
r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
if (r.restartDelay < minDuration) {
r.restartDelay = minDuration;
}
}
r.nextRestartTime = now + r.restartDelay;
// 调度重启
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
}
重启时间计算:
- 首次重启: 1秒
- 第二次: 2秒
- 第三次: 4秒
- 第四次: 8秒
- ...
- 最大延迟: 约1小时
6. 前台服务(Foreground Service)
6.1 前台服务概述
前台服务执行用户可感知的操作,必须显示通知。从Android 8.0(API 26)开始,后台应用启动服务受限,前台服务成为重要机制。
使用场景:
- 音乐播放
- 导航
- 文件下载
- 健身追踪
- VOIP通话
6.2 前台服务类型 (Android 10+)
文件位置 : frameworks/base/core/java/android/content/pm/ServiceInfo.java
java
public class ServiceInfo extends ComponentInfo {
/** 不指定类型 (默认) */
public static final int FOREGROUND_SERVICE_TYPE_NONE = 0;
/** 数据同步 */
public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1 << 0;
/** 媒体播放 */
public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 1 << 1;
/** 电话 */
public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 1 << 2;
/** 位置 */
public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 1 << 3;
/** 互联设备 */
public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 1 << 4;
/** 媒体投影 */
public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 1 << 5;
/** 相机 */
public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 1 << 6;
/** 麦克风 */
public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 1 << 7;
/** 健康 (Android 10+) */
public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 1 << 8;
/** 远程消息 (Android 11+) */
public static final int FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING = 1 << 9;
/** 系统豁免 (Android 11+) */
public static final int FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED = 1 << 10;
/** 短期服务 (Android 12+) */
public static final int FOREGROUND_SERVICE_TYPE_SHORT_SERVICE = 1 << 11;
/** 文件管理 (Android 14+) */
public static final int FOREGROUND_SERVICE_TYPE_FILE_MANAGEMENT = 1 << 12;
/** 特殊使用 (Android 14+) */
public static final int FOREGROUND_SERVICE_TYPE_SPECIAL_USE = 1 << 13;
/** Manifest中声明 */
public static final int FOREGROUND_SERVICE_TYPE_MANIFEST = -1;
}
6.3 前台服务权限要求 (Android 14+)
AndroidManifest.xml声明:
xml
<manifest>
<!-- 基础前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 类型特定权限 (Android 14+) -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application>
<service
android:name=".MusicPlayerService"
android:foregroundServiceType="mediaPlayback"
android:exported="false" />
<service
android:name=".NavigationService"
android:foregroundServiceType="location|connectedDevice"
android:exported="false" />
</application>
</manifest>
6.4 启动前台服务
6.4.1 从应用层启动
java
public class MusicPlayerService extends Service {
private static final int NOTIFICATION_ID = 1001;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 必须在5秒内调用startForeground(),否则ANR
createNotificationChannel();
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("音乐播放中")
.setContentText("正在播放: 歌曲名称")
.setSmallIcon(R.drawable.ic_music)
.setOngoing(true) // 不可清除
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.build();
// 指定前台服务类型
startForeground(NOTIFICATION_ID, notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
return START_STICKY;
}
@Override
public void onDestroy() {
// 停止前台服务
stopForeground(STOP_FOREGROUND_REMOVE);
super.onDestroy();
}
}
// Activity中启动
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(this, MusicPlayerService.class));
} else {
startService(new Intent(this, MusicPlayerService.class));
}
6.4.2 Framework层检查
文件位置 : frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
java
private int shouldAllowFgsStartForegroundWithBindingCheckLocked(...) {
// 1. 检查TOP进程 (前台可见)
if (callerApp.mState.getCurProcState() <= PROCESS_STATE_TOP) {
return REASON_PROC_STATE_TOP;
}
// 2. 系统UID豁免
if (callingUid == SYSTEM_UID || callingUid == ROOT_UID) {
return REASON_SYSTEM_UID;
}
// 3. SYSTEM_ALERT_WINDOW权限
if (mAm.hasSystemAlertWindowPermission(callingUid, callingPackage)) {
return REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
}
// 4. 从前台服务绑定
if ((callerApp.mState.getCurProcState() < PROCESS_STATE_BOUND_TOP) &&
(mAm.getUidState(callingUid) <=
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE)) {
return REASON_FGS_BINDING;
}
// 5. START_ACTIVITIES_FROM_BACKGROUND权限
if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
callingPid, callingUid) == PERMISSION_GRANTED) {
return REASON_BACKGROUND_ACTIVITY_PERMISSION;
}
// 6. 临时白名单 (如推送消息)
if (mAm.mInternal.isAllowlistedForFgsStartLOSP(callingUid)) {
return REASON_TEMP_ALLOWED_WHILE_IN_USE;
}
// 7. Device Owner / Profile Owner
if (mAm.mInternal.isDeviceOwner(callingUid)) {
return REASON_DEVICE_OWNER;
}
// 8. Instrumentation (测试)
if (callerApp.getActiveInstrumentation() != null) {
return REASON_INSTR_BACKGROUND_FGS_PERMISSION;
}
// 拒绝启动
return PowerExemptionManager.REASON_DENIED;
}
6.5 前台服务超时机制
文件位置 : frameworks/base/core/java/android/app/ActivityThread.java
java
void throwRemoteServiceException(String message, IBinder token) {
// 查找对应的Service
CreateServiceData data = mServicesData.get(token);
if (data != null) {
// 获取startForegroundService的调用栈
StackTrace st = Service.getStartForegroundServiceStackTrace(
data.info.name);
if (st != null) {
message = message + "\n" + st.toString();
}
}
// 抛出异常,导致应用崩溃
throw new RemoteServiceException(message);
}
超时检测:
startForegroundService()后必须在5秒内 调用startForeground()- 超时会抛出
ForegroundServiceDidNotStartInTimeException - Android 12+: 短期前台服务(SHORT_SERVICE)超时时间为3分钟
6.6 前台服务适配要点
Android 8.0 (API 26)
- 引入
startForegroundService() - 后台应用启动服务限制
Android 9.0 (API 28)
- 需要
FOREGROUND_SERVICE权限
Android 10 (API 29)
- 引入前台服务类型
- 后台位置访问需要额外权限
Android 11 (API 30)
- Manifest必须声明
foregroundServiceType - 相机/麦克风类型需要在使用时持续显示通知
Android 12 (API 31)
- 后台启动前台服务严格限制
- 引入短期前台服务(3分钟自动停止)
- 增加豁免场景(推送高优先级消息等)
Android 13 (API 33)
- 通知权限独立(
POST_NOTIFICATIONS) - 前台服务Task Manager管理
Android 14 (API 34)
- 每种前台服务类型需要独立权限
- 数据同步类型限制加强
- 引入用户发起的数据传输作业(User-Initiated Data Transfer Jobs)
Android 15 (当前版本)
- 增强前台服务监控
- 更严格的类型匹配检查
- 改进通知样式要求
适配代码示例:
java
// 兼容不同Android版本的前台服务启动
public class ForegroundServiceHelper {
public static void startForegroundService(Context context, Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Android 8.0+
context.startForegroundService(intent);
} else {
context.startService(intent);
}
}
public static void startForegroundWithType(Service service, int id,
Notification notification, int fgsType) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10+: 指定类型
service.startForeground(id, notification, fgsType);
} else {
// Android 8.0-9.0: 不支持类型
service.startForeground(id, notification);
}
}
public static boolean checkForegroundServicePermission(Context context,
String fgsTypePermission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
// Android 14+: 检查类型特定权限
return context.checkSelfPermission(fgsTypePermission)
== PackageManager.PERMISSION_GRANTED;
}
return true; // 低版本不需要
}
}
7. Binder通信机制
7.1 Binder架构图
┌──────────────────────────────────────────────────────────────┐
│ Client Process │
│ │
│ ┌───────────────┐ ┌──────────────┐ │
│ │ IActivityManager │ ServiceConnection │
│ │ (Proxy) │ │ (Stub) │ │
│ └───────┬───────┘ └───────▲──────┘ │
│ │ │ │
└───────────┼─────────────────────────┼────────────────────────┘
│ Binder IPC │ Binder IPC
▼ │
┌───────────────────────────────────────────────────────────────┐
│ Binder Driver │
│ (/dev/binder) │
└───────────────────────────────────────────────────────────────┘
│ ▲
│ Binder IPC │ Binder IPC
┌───────────┼─────────────────────────┼────────────────────────┐
│ ▼ │ │
│ ┌───────────────┐ ┌──────────────┐ │
│ │ ActivityManagerService │ IServiceConnection │
│ │ (Stub) │ │ (Proxy) │ │
│ └───────────────┘ └───────────────┘ │
│ │
│ System Server Process │
└──────────────────────────────────────────────────────────────┘
7.2 Binder核心类
文件位置 : frameworks/base/core/java/android/os/Binder.java
java
public class Binder implements IBinder {
/**
* Binder本地对象
* Service端实现
*/
public Binder() {
mObject = getNativeBBinderHolder();
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
}
/**
* 获取调用者UID
*/
public static final native int getCallingUid();
/**
* 获取调用者PID
*/
public static final native int getCallingPid();
/**
* 清除调用者身份,返回token
* 用于临时切换到Service进程身份
*/
public static final native long clearCallingIdentity();
/**
* 恢复调用者身份
*/
public static final native void restoreCallingIdentity(long token);
/**
* Binder远程调用
*/
public final boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
// ...
}
/**
* 本地方法实现
* 子类重写以处理请求
*/
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
// ...
}
}
7.3 AIDL生成的Binder代码
IActivityManager.aidl (简化版):
java
interface IActivityManager {
ComponentName startService(
in IApplicationThread caller,
in Intent service,
String resolvedType,
boolean requireForeground,
String callingPackage,
String callingFeatureId,
int userId);
int bindServiceInstance(
in IApplicationThread caller,
in IBinder token,
in Intent service,
String resolvedType,
in IServiceConnection connection,
long flags,
String instanceName,
String callingPackage,
int userId);
}
生成的Java代码:
java
public interface IActivityManager extends IInterface {
// Stub: Server端实现
public static abstract class Stub extends Binder implements IActivityManager {
private static final String DESCRIPTOR = "android.app.IActivityManager";
// Transaction代码
static final int TRANSACTION_startService = IBinder.FIRST_CALL_TRANSACTION + 0;
static final int TRANSACTION_bindServiceInstance = IBinder.FIRST_CALL_TRANSACTION + 1;
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case TRANSACTION_startService: {
data.enforceInterface(DESCRIPTOR);
IApplicationThread caller = IApplicationThread.Stub
.asInterface(data.readStrongBinder());
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
boolean requireForeground = data.readInt() != 0;
String callingPackage = data.readString();
String callingFeatureId = data.readString();
int userId = data.readInt();
// 调用实际实现
ComponentName result = this.startService(caller, service,
resolvedType, requireForeground, callingPackage,
callingFeatureId, userId);
reply.writeNoException();
if (result != null) {
reply.writeInt(1);
result.writeToParcel(reply, 0);
} else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_bindServiceInstance: {
// 类似处理...
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
// Proxy: Client端代理
private static class Proxy implements IActivityManager {
private IBinder mRemote;
Proxy(IBinder remote) {
mRemote = remote;
}
@Override
public ComponentName startService(IApplicationThread caller,
Intent service, String resolvedType, boolean requireForeground,
String callingPackage, String callingFeatureId, int userId)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
ComponentName result;
try {
data.writeInterfaceToken(DESCRIPTOR);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeInt(requireForeground ? 1 : 0);
data.writeString(callingPackage);
data.writeString(callingFeatureId);
data.writeInt(userId);
// 发起Binder调用
mRemote.transact(TRANSACTION_startService, data, reply, 0);
reply.readException();
if (reply.readInt() != 0) {
result = ComponentName.CREATOR.createFromParcel(reply);
} else {
result = null;
}
} finally {
reply.recycle();
data.recycle();
}
return result;
}
}
}
}
7.4 Service中的Binder通信
7.4.1 Bound Service示例
java
// Service端
public class DownloadService extends Service {
private final IBinder binder = new DownloadBinder();
// 本地Binder (同进程通信)
public class DownloadBinder extends Binder {
public DownloadService getService() {
return DownloadService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void startDownload(String url) {
// 下载逻辑
}
public int getProgress() {
return progress;
}
}
// Client端
public class MainActivity extends Activity {
private DownloadService downloadService;
private boolean bound = false;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
DownloadService.DownloadBinder binder =
(DownloadService.DownloadBinder) service;
downloadService = binder.getService();
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, DownloadService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (bound) {
unbindService(connection);
bound = false;
}
}
}
7.4.2 AIDL跨进程通信
IDownloadService.aidl:
java
package com.example.app;
import com.example.app.IDownloadCallback;
interface IDownloadService {
void startDownload(String url);
int getProgress(String url);
void registerCallback(IDownloadCallback callback);
void unregisterCallback(IDownloadCallback callback);
}
IDownloadCallback.aidl:
java
package com.example.app;
interface IDownloadCallback {
void onProgressUpdate(String url, int progress);
void onDownloadComplete(String url);
}
Service实现:
java
public class DownloadService extends Service {
private RemoteCallbackList<IDownloadCallback> callbacks =
new RemoteCallbackList<>();
private final IDownloadService.Stub binder = new IDownloadService.Stub() {
@Override
public void startDownload(String url) throws RemoteException {
// 检查调用者权限
int callingUid = Binder.getCallingUid();
if (!checkPermission(callingUid)) {
throw new SecurityException("Permission denied");
}
// 执行下载
DownloadService.this.startDownload(url);
}
@Override
public int getProgress(String url) throws RemoteException {
return DownloadService.this.getProgress(url);
}
@Override
public void registerCallback(IDownloadCallback callback)
throws RemoteException {
if (callback != null) {
callbacks.register(callback);
}
}
@Override
public void unregisterCallback(IDownloadCallback callback)
throws RemoteException {
if (callback != null) {
callbacks.unregister(callback);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private void notifyProgress(String url, int progress) {
final int count = callbacks.beginBroadcast();
for (int i = 0; i < count; i++) {
try {
callbacks.getBroadcastItem(i).onProgressUpdate(url, progress);
} catch (RemoteException e) {
// Client已死亡,RemoteCallbackList会自动处理
}
}
callbacks.finishBroadcast();
}
}
Client实现:
java
public class MainActivity extends Activity {
private IDownloadService downloadService;
private IDownloadCallback callback = new IDownloadCallback.Stub() {
@Override
public void onProgressUpdate(String url, int progress)
throws RemoteException {
// 注意: 这里运行在Binder线程,需要切换到主线程
runOnUiThread(() -> {
progressBar.setProgress(progress);
});
}
@Override
public void onDownloadComplete(String url) throws RemoteException {
runOnUiThread(() -> {
Toast.makeText(MainActivity.this, "下载完成",
Toast.LENGTH_SHORT).show();
});
}
};
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadService = IDownloadService.Stub.asInterface(service);
try {
downloadService.registerCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
downloadService = null;
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, DownloadService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (downloadService != null) {
try {
downloadService.unregisterCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
unbindService(connection);
}
}
}
7.5 Binder线程池
Binder调用在Binder线程池中执行,不是主线程:
java
// Service的onBind/onStartCommand等回调运行在主线程
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Thread: " + Thread.currentThread().getName());
// 输出: main
return START_STICKY;
}
// AIDL接口方法运行在Binder线程
@Override
public void startDownload(String url) throws RemoteException {
Log.d(TAG, "Thread: " + Thread.currentThread().getName());
// 输出: Binder:12345_1 (Binder线程池)
// 如果需要更新UI,必须切换到主线程
handler.post(() -> {
// 更新UI
});
}
Binder线程池配置:
- 默认最大16个线程
- 应用进程启动时创建
- 自动管理,无需手动创建
8. 应用层使用指南
8.1 基本Service实现
java
public class BasicService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service Created");
// 初始化资源
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service Started");
if (intent != null) {
String action = intent.getAction();
// 处理不同的action
}
// 执行后台任务
new Thread(() -> {
// 耗时操作
doWork();
// 完成后停止Service
stopSelf(startId);
}).start();
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// 不提供绑定功能
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service Destroyed");
// 释放资源
}
}
8.2 前台Service实现
java
public class MusicPlayerService extends Service {
private static final String CHANNEL_ID = "music_player_channel";
private static final int NOTIFICATION_ID = 1001;
private MediaPlayer mediaPlayer;
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
if ("PLAY".equals(action)) {
startPlaying();
startForeground(NOTIFICATION_ID, createNotification("播放中"));
} else if ("PAUSE".equals(action)) {
pausePlaying();
updateNotification("已暂停");
} else if ("STOP".equals(action)) {
stopPlaying();
stopForeground(STOP_FOREGROUND_REMOVE);
stopSelf();
}
return START_STICKY;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"音乐播放",
NotificationManager.IMPORTANCE_LOW);
channel.setDescription("音乐播放控制");
channel.setShowBadge(false);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
private Notification createNotification(String status) {
Intent playIntent = new Intent(this, MusicPlayerService.class)
.setAction("PLAY");
PendingIntent playPendingIntent = PendingIntent.getService(
this, 0, playIntent, PendingIntent.FLAG_IMMUTABLE);
Intent pauseIntent = new Intent(this, MusicPlayerService.class)
.setAction("PAUSE");
PendingIntent pausePendingIntent = PendingIntent.getService(
this, 1, pauseIntent, PendingIntent.FLAG_IMMUTABLE);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("音乐播放器")
.setContentText(status)
.setSmallIcon(R.drawable.ic_music)
.setOngoing(true)
.addAction(R.drawable.ic_play, "播放", playPendingIntent)
.addAction(R.drawable.ic_pause, "暂停", pausePendingIntent)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.build();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
super.onDestroy();
}
}
8.3 Bound Service实现
java
// 同进程通信
public class LocalService extends Service {
private final IBinder binder = new LocalBinder();
private Random random = new Random();
public class LocalBinder extends Binder {
public LocalService getService() {
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public int getRandomNumber() {
return random.nextInt(100);
}
}
// Activity中使用
public class MainActivity extends Activity {
private LocalService service;
private boolean bound = false;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
LocalService.LocalBinder localBinder =
(LocalService.LocalBinder) binder;
service = localBinder.getService();
bound = true;
// 可以调用Service方法
int number = service.getRandomNumber();
}
@Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (bound) {
unbindService(connection);
bound = false;
}
}
}
8.4 IntentService实现 (已废弃,使用WorkManager替代)
java
// 注意: IntentService在Android 11+已废弃
// 推荐使用WorkManager或JobScheduler
public class DownloadService extends IntentService {
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// 运行在工作线程
if (intent != null) {
String url = intent.getStringExtra("url");
downloadFile(url);
}
// 自动stopSelf()
}
}
8.5 JobIntentService (推荐替代方案)
java
public class DownloadJobService extends JobIntentService {
private static final int JOB_ID = 1000;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, DownloadJobService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
// 运行在后台线程
String url = intent.getStringExtra("url");
downloadFile(url);
}
}
// 使用
Intent intent = new Intent();
intent.putExtra("url", "https://example.com/file.zip");
DownloadJobService.enqueueWork(this, intent);
8.6 WorkManager (最佳实践)
java
// 定义Worker
public class DownloadWorker extends Worker {
public DownloadWorker(@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public Result doWork() {
String url = getInputData().getString("url");
try {
downloadFile(url);
return Result.success();
} catch (Exception e) {
return Result.retry();
}
}
}
// 调度任务
Data inputData = new Data.Builder()
.putString("url", "https://example.com/file.zip")
.build();
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build();
OneTimeWorkRequest downloadWork = new OneTimeWorkRequest.Builder(DownloadWorker.class)
.setInputData(inputData)
.setConstraints(constraints)
.build();
WorkManager.getInstance(context).enqueue(downloadWork);
9. 关键类与接口
9.1 应用层核心类
| 类名 | 路径 | 说明 |
|---|---|---|
Service |
android.app.Service | Service基类 |
Context |
android.content.Context | 提供startService/bindService接口 |
ContextImpl |
android.app.ContextImpl | Context实现类 |
Intent |
android.content.Intent | Service启动/绑定参数 |
ServiceConnection |
android.content.ServiceConnection | 绑定回调接口 |
IBinder |
android.os.IBinder | Binder接口 |
Binder |
android.os.Binder | Binder本地对象 |
9.2 Framework层核心类
| 类名 | 路径 | 说明 |
|---|---|---|
ActivityManagerService |
com.android.server.am.ActivityManagerService | 系统服务 |
ActiveServices |
com.android.server.am.ActiveServices | Service管理核心 |
ServiceRecord |
com.android.server.am.ServiceRecord | Service记录 |
ConnectionRecord |
com.android.server.am.ConnectionRecord | 连接记录 |
ProcessRecord |
com.android.server.am.ProcessRecord | 进程记录 |
ActivityThread |
android.app.ActivityThread | 应用主线程 |
ApplicationThread |
android.app.ActivityThread.ApplicationThread | Binder通信对象 |
9.3 AIDL接口
| 接口 | 路径 | 说明 |
|---|---|---|
IActivityManager |
android.app.IActivityManager | AMS Binder接口 |
IApplicationThread |
android.app.IApplicationThread | 应用进程Binder接口 |
IServiceConnection |
android.app.IServiceConnection | ServiceConnection Binder接口 |
9.4 关键数据结构
ServiceRecord (简化)
java
final class ServiceRecord extends Binder {
final ComponentName name; // Service组件名
final String shortInstanceName; // 短名称
final Intent.FilterComparison intent; // 启动Intent
final ServiceInfo serviceInfo; // Service信息
final ApplicationInfo appInfo; // 应用信息
final String processName; // 进程名
final String permission; // 所需权限
ProcessRecord app; // 所属进程
ProcessRecord isolatedProc; // 隔离进程
boolean startRequested; // 是否通过start启动
boolean stopIfKilled; // 是否在killed后停止
boolean callStart; // 是否调用onStartCommand
int lastStartId; // 最后的startId
long createRealTime; // 创建时间
long lastActivity; // 最后活动时间
// 绑定相关
final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings =
new ArrayMap<>();
private final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections =
new ArrayMap<>();
// 前台服务相关
boolean isForeground; // 是否前台服务
int foregroundId; // 通知ID
Notification foregroundNoti; // 通知对象
int foregroundServiceType; // 前台服务类型
// 重启相关
long restartDelay; // 重启延迟
long restartTime; // 重启时间
int restartCount; // 重启次数
}
ConnectionRecord
java
final class ConnectionRecord {
final AppBindRecord binding; // 绑定记录
final ActivityServiceConnectionsHolder activity; // Activity持有者
final IServiceConnection conn; // 连接对象 (Binder)
final int flags; // 绑定标志
final int clientLabel; // 客户端标签
final PendingIntent clientIntent; // 客户端Intent
String stringName; // 字符串名称
boolean serviceDead; // Service是否死亡
// 所属的客户端进程
final ProcessRecord clientApp;
}
10. 最佳实践与注意事项
10.1 性能优化
10.1.1 避免ANR
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 错误: 耗时操作在主线程
// downloadFile(url); // ANR!
// 正确: 使用工作线程
new Thread(() -> {
downloadFile(url);
stopSelf(startId);
}).start();
return START_STICKY;
}
// 或使用线程池
private ExecutorService executor = Executors.newFixedThreadPool(4);
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
executor.execute(() -> {
downloadFile(url);
stopSelf(startId);
});
return START_STICKY;
}
10.1.2 及时stopSelf
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(() -> {
doWork();
// 使用带startId的版本,确保不会误停止后续start
stopSelf(startId);
// 错误: 可能停止后续的startService
// stopSelf();
}).start();
return START_STICKY;
}
10.1.3 合理使用IntentService替代
java
// 自动在工作线程处理,自动stopSelf
public class MyIntentService extends JobIntentService {
@Override
protected void onHandleWork(@NonNull Intent intent) {
// 自动在后台线程
doWork();
// 自动stopSelf
}
}
10.2 内存泄漏防范
10.2.1 正确管理ServiceConnection
java
public class MainActivity extends Activity {
private ServiceConnection connection;
private boolean bound = false;
@Override
protected void onStart() {
super.onStart();
connection = new ServiceConnection() { ... };
bindService(intent, connection, Context.BIND_AUTO_CREATE);
bound = true;
}
@Override
protected void onStop() {
super.onStop();
// 必须unbind,否则泄漏
if (bound) {
unbindService(connection);
bound = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 双重保险
if (bound) {
try {
unbindService(connection);
} catch (IllegalArgumentException e) {
// 已经unbind,忽略
}
bound = false;
}
}
}
10.2.2 避免Context泄漏
java
// 错误: Service中持有Activity引用
public class MyService extends Service {
private Activity activity; // 泄漏!
public void setActivity(Activity activity) {
this.activity = activity;
}
}
// 正确: 使用ApplicationContext
public class MyService extends Service {
private Context appContext;
@Override
public void onCreate() {
super.onCreate();
appContext = getApplicationContext();
}
}
10.2.3 AIDL回调清理
java
public class MyService extends Service {
private RemoteCallbackList<ICallback> callbacks = new RemoteCallbackList<>();
private final IMyService.Stub binder = new IMyService.Stub() {
@Override
public void registerCallback(ICallback callback) {
callbacks.register(callback);
}
@Override
public void unregisterCallback(ICallback callback) {
callbacks.unregister(callback);
}
};
@Override
public void onDestroy() {
// 清理所有回调
callbacks.kill();
super.onDestroy();
}
}
10.3 安全性考虑
10.3.1 Service导出控制
xml
<!-- 不需要跨应用访问的Service -->
<service
android:name=".MyService"
android:exported="false" />
<!-- 需要导出的Service,必须添加权限 -->
<permission
android:name="com.example.app.permission.ACCESS_SERVICE"
android:protectionLevel="signature" />
<service
android:name=".SharedService"
android:exported="true"
android:permission="com.example.app.permission.ACCESS_SERVICE" />
10.3.2 Intent验证
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
return START_STICKY;
}
// 验证来源
String action = intent.getAction();
if (action == null || !action.startsWith("com.example.app")) {
Log.w(TAG, "Invalid action: " + action);
return START_NOT_STICKY;
}
// 验证数据
String url = intent.getStringExtra("url");
if (!isValidUrl(url)) {
Log.w(TAG, "Invalid URL: " + url);
return START_NOT_STICKY;
}
// 处理...
return START_STICKY;
}
10.3.3 Binder权限检查
java
private final IMyService.Stub binder = new IMyService.Stub() {
@Override
public void sensitiveOperation() throws RemoteException {
// 检查调用者权限
if (checkCallingPermission("com.example.app.permission.ADMIN")
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires ADMIN permission");
}
// 检查调用者包名
int callingUid = Binder.getCallingUid();
String[] packages = getPackageManager().getPackagesForUid(callingUid);
if (!isAllowedPackage(packages)) {
throw new SecurityException("Package not allowed");
}
// 执行操作
doSensitiveOperation();
}
};
10.4 兼容性处理
10.4.1 Android 8.0+ 后台限制
java
public void startMyService() {
Intent intent = new Intent(this, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Android 8.0+: 使用前台服务
startForegroundService(intent);
} else {
startService(intent);
}
}
// Service中必须调用startForeground
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification notification = createNotification();
startForeground(1, notification);
}
return START_STICKY;
}
10.4.2 Android 12+ 前台服务限制
java
public void startForegroundService() {
// 检查是否允许启动前台服务
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// Android 12+: 检查前台服务启动条件
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (!am.isBackgroundRestricted()) {
startForegroundServiceInternal();
} else {
// 使用WorkManager或Alarm替代
scheduleWithWorkManager();
}
} else {
startForegroundServiceInternal();
}
}
10.4.3 Android 14+ 类型权限
java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
// Android 14+: 检查类型特定权限
if (checkSelfPermission("android.permission.FOREGROUND_SERVICE_LOCATION")
!= PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "Missing FOREGROUND_SERVICE_LOCATION permission");
stopSelf();
return START_NOT_STICKY;
}
startForeground(NOTIFICATION_ID, createNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
} else {
startForeground(NOTIFICATION_ID, createNotification());
}
return START_STICKY;
}
10.5 测试建议
10.5.1 单元测试
java
@RunWith(AndroidJUnit4.class)
public class MyServiceTest {
@Rule
public ServiceTestRule serviceRule = new ServiceTestRule();
@Test
public void testServiceBinding() throws TimeoutException {
Intent intent = new Intent(
ApplicationProvider.getApplicationContext(),
MyService.class);
IBinder binder = serviceRule.bindService(intent);
MyService.LocalBinder localBinder = (MyService.LocalBinder) binder;
MyService service = localBinder.getService();
assertNotNull(service);
assertEquals(expected, service.getData());
}
}
10.5.2 集成测试
java
@RunWith(AndroidJUnit4.class)
public class ServiceIntegrationTest {
@Test
public void testServiceStartAndStop() {
Context context = ApplicationProvider.getApplicationContext();
Intent intent = new Intent(context, MyService.class);
// 启动服务
ComponentName component = context.startService(intent);
assertNotNull(component);
// 验证服务运行
ActivityManager am = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
boolean running = false;
for (ActivityManager.RunningServiceInfo service :
am.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(
service.service.getClassName())) {
running = true;
break;
}
}
assertTrue(running);
// 停止服务
boolean stopped = context.stopService(intent);
assertTrue(stopped);
}
}
10.6 常见错误与解决方案
| 错误 | 原因 | 解决方案 |
|---|---|---|
IllegalStateException: Not allowed to start service |
Android 8.0+后台启动限制 | 使用startForegroundService() |
ForegroundServiceStartNotAllowedException |
Android 12+前台服务限制 | 检查启动条件或使用WorkManager |
RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground() |
5秒内未调用startForeground() |
在onCreate()或onStartCommand()中立即调用 |
SecurityException: Permission Denial |
缺少权限或Service未导出 | 检查权限声明和exported属性 |
BinderProxy@xxx is not valid |
Service已死亡 | 处理onServiceDisconnected()回调 |
IllegalArgumentException: Service not registered |
重复unbindService() |
使用标志位避免重复unbind |
| ANR | onStartCommand()执行耗时操作 |
使用工作线程或IntentService |
附录A: Service生命周期完整流程图
startService() / bindService()
onStartCommand()
onBind()
onStartCommand() (再次start)
stopService() / stopSelf()
unbindService()
bindService() (如果onUnbind返回true)
onRebind()
没有其他绑定且未start
unbindService()
stopService()
仍有start
仍有bind
onDestroy()
Created
Started
Bound
Destroyed
Unbound
Rebound
PartialDestroy
附录B: 常用命令
B.1 adb命令
bash
# 启动Service
adb shell am startservice -n com.example.app/.MyService
# 启动前台Service
adb shell am start-foreground-service -n com.example.app/.MyService
# 停止Service
adb shell am stopservice -n com.example.app/.MyService
# 查看运行中的Service
adb shell dumpsys activity services
# 查看特定Service详情
adb shell dumpsys activity services com.example.app/.MyService
# 查看进程信息
adb shell ps | grep com.example.app
# 查看Binder信息
adb shell cat /sys/kernel/debug/binder/stats
# 查看内存使用
adb shell dumpsys meminfo com.example.app
B.2 logcat过滤
bash
# 过滤Service相关日志
adb logcat | grep -i "service"
# 过滤ActivityManager日志
adb logcat ActivityManager:V *:S
# 过滤特定TAG
adb logcat MyService:D *:S
# 过滤Binder日志
adb logcat | grep -i "binder"
附录C: 参考资源
C.1 官方文档
- Services Overview | Android Developers
- Bound Services | Android Developers
- Foreground Services | Android Developers
- AIDL | Android Developers
C.2 源码路径
frameworks/base/core/java/android/app/frameworks/base/services/core/java/com/android/server/am/frameworks/base/core/jni/android_util_Binder.cpp
C.3 相关技术
- WorkManager: 后台任务调度的推荐方案
- JobScheduler: 系统级任务调度
- AlarmManager: 定时任务
- Foreground Services: 用户可感知的后台服务
附录D: 版本变更历史
| Android版本 | API Level | 重要变更 |
|---|---|---|
| Android 5.0 | 21 | 必须使用显式Intent启动Service |
| Android 8.0 | 26 | 后台服务限制,引入前台服务 |
| Android 9.0 | 28 | FOREGROUND_SERVICE权限 |
| Android 10 | 29 | 前台服务类型 |
| Android 11 | 30 | Manifest必须声明类型 |
| Android 12 | 31 | 后台启动前台服务严格限制,短期前台服务 |
| Android 13 | 33 | 通知权限独立 |
| Android 14 | 34 | 类型特定权限 |
| Android 15 | 35 | 增强监控和限制 |
致敬前辈,砥砺前行!