02-Service启动与绑定原理 - 后台任务的正确打开方式
·
Service启动与绑定原理 - 后台任务的正确打开方式
摘要
本文深入剖析Android Service组件的启动(startService)和绑定(bindService)两种使用方式的底层实现原理。基于AOSP源码追踪从应用层调用到ServiceManagerService处理、Service实例创建、生命周期回调的完整链路。文章详细分析前台服务、IntentService、AIDL跨进程通信等核心技术,并结合某IoT项目实战经验,提供Service使用的最佳实践和性能优化建议。
关键词:Service启动流程、bindService原理、ServiceManagerService、AIDL、前台服务、ANR分析
一、引言
1.1 Service的重要性
Service是Android四大组件之一,专门用于处理后台任务。无论是音乐播放、文件下载、数据同步还是IoT设备的长连接管理,Service都扮演着核心角色。
应用场景:
- 后台数据处理(日志上传、数据同步)
- 长连接维持(IoT设备通信、推送服务)
- 音视频播放(MediaPlayer后台播放)
- 定时任务(闹钟、提醒)
1.2 Service的两种使用方式
| 方式 | 生命周期 | 通信方式 | 典型场景 |
|---|---|---|---|
| startService | 独立于调用者 | 单向通信 | 后台下载、日志上传 |
| bindService | 依赖调用者 | 双向通信 | 跨进程调用、实时数据交互 |
1.3 核心类概览
二、startService启动流程
2.1 应用层调用入口
// 应用代码
Intent intent = new Intent(this, MyService.class);
intent.putExtra("key", "value");
startService(intent);
2.2 ContextImpl.startService()
// frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
// 验证Intent
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// 调用AMS
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
} else if (cn.getPackageName().equals("?")) {
throw new IllegalStateException(
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
2.3 ActivityManagerService处理
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// 拒绝可能包含文件描述符的Intent
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
// 委托给ActiveServices处理
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
2.4 ActiveServices.startServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int callingPid, int callingUid, boolean fgRequired,
String callingPackage, final int userId)
throws TransactionTooLargeException {
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException("Unable to find app for caller " + caller);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
// 解析Service组件
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
// 权限检查
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
callingUid, service, callerFg, userId)) {
return null;
}
// 前台服务检查
if (fgRequired) {
if (!r.isForeground) {
// 需要启动为前台服务但未设置
return new ComponentName("?", "foreground service required");
}
}
// 后台启动限制检查 (Android 8.0+)
if (!r.mAppInfo.isSystemApp()) {
boolean allowed = false;
if (callerApp != null && callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND) {
// 前台应用可以启动后台服务
allowed = true;
} else if (mAm.isUidActiveLocked(callingUid)) {
// UID处于活跃状态
allowed = true;
}
if (!allowed && !fgRequired) {
// Android 8.0+ 后台启动限制
return new ComponentName("?", "background service restriction");
}
}
// 真正的启动逻辑
return startServiceInnerLocked(r, service, callingUid, callingPid,
fgRequired, callerFg, null);
}
2.5 启动Service实例
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
int callingUid, int callingPid, boolean fgRequired, boolean callerFg,
Bundle options) throws TransactionTooLargeException {
// Service状态更新
r.callStart = false;
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
r.fgRequired = fgRequired;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants, callingUid));
// 前台服务特殊处理
if (fgRequired) {
r.fgWaiting = true;
scheduleServiceForegroundTransitionTimeoutLocked(r);
}
final ServiceMap smap = getServiceMapLocked(r.userId);
boolean addToStarting = false;
// 非前台服务的特殊处理
if (!callerFg && !fgRequired && r.app == null
&& mAm.mUserController.hasStartedUserState(r.userId)) {
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
// 延迟启动服务,避免同时启动多个后台服务
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
addToStarting = true;
}
}
// 启动Service
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
ServiceRecord r, boolean callerFg, boolean addToStarting)
throws TransactionTooLargeException {
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
// 启动Service(创建进程或在已有进程中启动)
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
if (first) {
smap.rescheduleDelayedStartsLocked();
}
} else if (callerFg || r.fgRequired) {
smap.ensureNotStartingBackgroundLocked(r);
}
return r.name;
}
2.6 bringUpServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags,
boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
// Service已在运行,直接调用onStartCommand
sendServiceArgsLocked(r, execInFg, false);
return null;
}
if (!whileRestarting && mRestartingServices.contains(r)) {
// 等待重启完成
return null;
}
// 从延迟启动列表移除
if (mDelayedStartList.remove(r)) {
// ...
}
// 确保拥有者已启动
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "Unable to launch service " + r.intent.getIntent()
+ " U=" + r.userId + ": user " + r.userId + " is stopped";
return msg;
}
// 进程启动
final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {
try {
// 在已有进程中创建Service
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
// 进程死亡
}
}
} else {
app = r.isolatedProc;
}
// 进程不存在,需要启动新进程
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, false, isolated, false)) == null) {
String msg = "Unable to launch service " + r.intent.getIntent()
+ " from package " + r.packageName
+ ": process " + procName + " could not be started";
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
// 加入待启动列表
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
if (r.delayedStop) {
r.delayedStop = false;
if (r.startRequested) {
stopServiceLocked(r);
}
}
return null;
}
2.7 realStartServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
r.setProcess(app);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
// 调度Service超时检测(前台20秒,后台200秒)
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, true);
mAm.updateOomAdjLocked();
boolean created = false;
try {
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 通过Binder调用应用进程创建Service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
created = true;
} catch (DeadObjectException e) {
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// 创建失败清理
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
if (newService) {
app.services.remove(r);
r.setProcess(null);
}
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
// 如果Service已绑定,发送绑定回调
requestServiceBindingsLocked(r, execInFg);
// 更新Service状态
updateServiceClientActivitiesLocked(app, null, true);
// 如果是startService启动,调用onStartCommand
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null, 0));
}
sendServiceArgsLocked(r, execInFg, true);
// 前台服务处理
if (r.delayed) {
getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
r.delayedStop = false;
if (r.startRequested) {
stopServiceLocked(r);
}
}
}
2.8 应用进程创建Service
// frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
}
class H extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
}
}
}
private void handleCreateService(CreateServiceData data) {
// 获取LoadedApk
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 创建ContextImpl
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// 通过反射创建Service实例
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// 创建Application(如果不存在)
Application app = packageInfo.makeApplication(false, mInstrumentation);
// 初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 调用onCreate()
service.onCreate();
mServices.put(data.token, service);
// 通知AMS创建完成
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
2.9 sendServiceArgsLocked() - 调用onStartCommand
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
ArrayList<ServiceStartArgs> args = new ArrayList<>();
while (r.pendingStarts.size() > 0) {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
if (si.intent == null && N > 1) {
// 如果有多个挂起的启动,跳过空Intent
continue;
}
si.deliveredTime = SystemClock.uptimeMillis();
r.deliveredStarts.add(si);
si.deliveryCount++;
if (si.neededGrants != null) {
mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
si.getUriPermissionsLocked());
}
bumpServiceExecutingLocked(r, execInFg, "start");
if (!oomAdjusted) {
oomAdjusted = true;
mAm.updateOomAdjLocked(r.app, true);
}
args.add(new ServiceStartArgs(si.taskRemoved, si.id, si.intent));
}
ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
slice.setInlineCountLimit(4);
Exception caughtException = null;
try {
// 调用应用进程的onStartCommand
r.app.thread.scheduleServiceArgs(r, slice);
} catch (TransactionTooLargeException e) {
caughtException = e;
} catch (RemoteException e) {
caughtException = e;
} catch (Exception e) {
caughtException = e;
}
if (caughtException != null) {
// 异常处理
final boolean inDestroying = mDestroyingServices.contains(r);
for (int i=0; i<args.size(); i++) {
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
}
if (caughtException instanceof TransactionTooLargeException) {
throw (TransactionTooLargeException)caughtException;
}
}
}
2.10 应用进程调用onStartCommand
// frameworks/base/core/java/android/app/ActivityThread.java
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (data.args != null) {
data.args.setExtrasClassLoader(s.getClassLoader());
data.args.prepareToEnterProcess();
}
int res;
if (!data.taskRemoved) {
// 调用onStartCommand
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
// 任务被移除,调用onTaskRemoved
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
// 确保服务处于活跃状态
QueuedWork.waitToFinish();
try {
// 通知AMS执行完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to start service " + s
+ " with " + data.args + ": " + e.toString(), e);
}
}
}
}
2.11 startService完整流程图
三、bindService绑定流程
3.1 bindService调用入口
// 应用代码
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
// ServiceConnection回调
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取Service的Binder对象
MyService.MyBinder binder = (MyService.MyBinder) service;
myService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
};
3.2 ContextImpl.bindService()
// frameworks/base/core/java/android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
// 验证ServiceConnection
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
// 调用AMS绑定服务
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, 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();
}
}
关键点:
ServiceDispatcher将ServiceConnection转换为IServiceConnection Binder接口BIND_AUTO_CREATE标志表示Service不存在时自动创建
3.3 ServiceDispatcher封装
// frameworks/base/core/java/android/app/LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, 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
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
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 int mFlags;
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);
}
}
}
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mFlags = flags;
}
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// 已经连接,不需要回调
return;
}
if (service != null) {
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
service.linkToDeath(info.deathMonitor, 0);
mActiveConnections.put(name, info);
} catch (RemoteException e) {
mActiveConnections.remove(name);
return;
}
} else {
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
}
// 回调onServiceConnected
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
mConnection.onNullBinding(name);
}
}
}
3.4 ActiveServices.bindServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException("Unable to find app for caller " + caller);
}
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
if (activity == null) {
return 0;
}
}
// 解析Service
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
// 创建ConnectionRecord
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
activity.addConnection(c);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
// 启动Service(如果需要)
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
// 如果Service已启动,请求绑定
if (s.app != null && b.intent.received) {
// Service已运行且已绑定过,直接回调
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
// 如果Intent已请求过,不需要再次请求
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);
}
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
return 1;
}
3.5 requestServiceBindingLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// Service进程已死亡
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 调用Service.onBind()
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.getReportedProcState());
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
throw e;
} catch (RemoteException e) {
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
return false;
}
}
return true;
}
3.6 应用进程处理绑定
// frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindService(BindServiceData data) {
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(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
3.7 publishService返回Binder
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public 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 {
// 回调客户端的onServiceConnected
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);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
3.8 bindService完整流程图
四、AIDL跨进程通信
4.1 AIDL接口定义
// IMyService.aidl
package com.example.service;
interface IMyService {
String getData();
void setData(String data);
void registerCallback(IMyCallback callback);
}
// IMyCallback.aidl
package com.example.service;
interface IMyCallback {
void onDataChanged(String data);
}
4.2 Service端实现
public class MyService extends Service {
private final RemoteCallbackList<IMyCallback> callbacks = new RemoteCallbackList<>();
private String data = "Initial Data";
private final IMyService.Stub binder = new IMyService.Stub() {
@Override
public String getData() throws RemoteException {
return data;
}
@Override
public void setData(String newData) throws RemoteException {
data = newData;
// 通知所有注册的回调
final int N = callbacks.beginBroadcast();
for (int i = 0; i < N; i++) {
try {
callbacks.getBroadcastItem(i).onDataChanged(data);
} catch (RemoteException e) {
// 客户端可能已死亡
}
}
callbacks.finishBroadcast();
}
@Override
public void registerCallback(IMyCallback callback) throws RemoteException {
if (callback != null) {
callbacks.register(callback);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onDestroy() {
super.onDestroy();
callbacks.kill();
}
}
4.3 客户端使用
public class ClientActivity extends AppCompatActivity {
private IMyService myService;
private boolean isBound = false;
private final IMyCallback.Stub callback = new IMyCallback.Stub() {
@Override
public void onDataChanged(String data) throws RemoteException {
// 注意:此方法在Binder线程调用,需要切换到主线程
runOnUiThread(() -> {
Toast.makeText(ClientActivity.this, "Data: " + data, Toast.LENGTH_SHORT).show();
});
}
};
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = IMyService.Stub.asInterface(service);
isBound = true;
try {
// 注册回调
myService.registerCallback(callback);
// 获取数据
String data = myService.getData();
Log.d("Client", "Initial data: " + data);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
isBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
// 绑定Service
Intent intent = new Intent();
intent.setComponent(new ComponentName(
"com.example.service",
"com.example.service.MyService"));
bindService(intent, connection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(connection);
isBound = false;
}
}
public void updateData(String newData) {
if (isBound && myService != null) {
try {
myService.setData(newData);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
4.4 Binder通信机制
五、前台服务
5.1 前台服务的重要性
Android 8.0+对后台服务进行了严格限制,前台服务是保证长时间运行的关键。
5.2 启动前台服务
public class MusicService extends Service {
private static final int NOTIFICATION_ID = 1;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 创建通知渠道(Android 8.0+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"music_channel",
"Music Playback",
NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
// 创建通知
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
Notification notification = new NotificationCompat.Builder(this, "music_channel")
.setContentTitle("Music Player")
.setContentText("Playing music")
.setSmallIcon(R.drawable.ic_music)
.setContentIntent(pendingIntent)
.build();
// 启动前台服务
startForeground(NOTIFICATION_ID, notification);
return START_STICKY;
}
@Override
public void onDestroy() {
// 停止前台服务
stopForeground(true);
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
5.3 前台服务权限声明
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 9.0+ 需要指定前台服务类型 -->
<service
android:name=".MusicService"
android:foregroundServiceType="mediaPlayback"
android:exported="false" />
5.4 前台服务类型(Android 10+)
<!-- 前台服务类型 -->
<service
android:name=".LocationService"
android:foregroundServiceType="location" />
<!-- 多种类型组合 -->
<service
android:name=".MyService"
android:foregroundServiceType="location|camera" />
可用类型:
camera:相机dataSync:数据同步location:位置mediaPlayback:媒体播放mediaProjection:屏幕投影microphone:麦克风phoneCall:电话connectedDevice:连接设备
六、IntentService
6.1 IntentService原理
IntentService是Service的子类,自动在工作线程处理Intent,处理完成后自动停止。
// frameworks/base/core/java/android/app/IntentService.java
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 在工作线程处理Intent
onHandleIntent((Intent)msg.obj);
// 处理完成后停止服务
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
@Override
public void onCreate() {
super.onCreate();
// 创建工作线程
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
// 子类实现此方法处理Intent
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
6.2 IntentService使用示例
public class DownloadService extends IntentService {
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null) {
String url = intent.getStringExtra("url");
String filename = intent.getStringExtra("filename");
// 在工作线程执行下载
downloadFile(url, filename);
}
}
private void downloadFile(String url, String filename) {
try {
// 下载逻辑
Thread.sleep(5000); // 模拟下载
// 下载完成通知
sendBroadcast(new Intent("DOWNLOAD_COMPLETE"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
七、某IoT项目实战经验
7.1 项目背景
某IoT智能家居项目需要维持与设备的长连接,处理设备状态上报和远程控制指令。
7.2 架构设计
7.3 核心代码实现
public class DeviceService extends Service {
private final IBinder binder = new LocalBinder();
private MqttClient mqttClient;
private final RemoteCallbackList<IDeviceCallback> callbacks = new RemoteCallbackList<>();
public class LocalBinder extends Binder {
public DeviceService getService() {
return DeviceService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
// 初始化MQTT连接
initMqttConnection();
// 启动为前台服务
startForegroundService();
}
private void startForegroundService() {
// 创建通知
Notification notification = createNotification();
startForeground(1, notification);
}
private void initMqttConnection() {
try {
String broker = "tcp://mqtt.example.com:1883";
String clientId = "android_" + UUID.randomUUID().toString();
mqttClient = new MqttClient(broker, clientId, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setKeepAliveInterval(60);
options.setAutomaticReconnect(true);
mqttClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
// 连接断开,自动重连
notifyConnectionStatus(false);
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
// 处理设备消息
handleDeviceMessage(topic, new String(message.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// 消息发送完成
}
});
mqttClient.connect(options);
// 订阅设备主题
mqttClient.subscribe("devices/+/status", 1);
notifyConnectionStatus(true);
} catch (MqttException e) {
e.printStackTrace();
}
}
private void handleDeviceMessage(String topic, String payload) {
// 解析设备消息
try {
JSONObject json = new JSONObject(payload);
String deviceId = json.getString("deviceId");
String status = json.getString("status");
// 更新数据库
updateDeviceStatus(deviceId, status);
// 通知所有回调
final int N = callbacks.beginBroadcast();
for (int i = 0; i < N; i++) {
try {
callbacks.getBroadcastItem(i).onDeviceStatusChanged(deviceId, status);
} catch (RemoteException e) {
// 客户端可能已死亡
}
}
callbacks.finishBroadcast();
} catch (JSONException e) {
e.printStackTrace();
}
}
public void controlDevice(String deviceId, String command) {
try {
JSONObject json = new JSONObject();
json.put("deviceId", deviceId);
json.put("command", command);
json.put("timestamp", System.currentTimeMillis());
String topic = "devices/" + deviceId + "/control";
mqttClient.publish(topic, json.toString().getBytes(), 1, false);
} catch (Exception e) {
e.printStackTrace();
}
}
public void registerCallback(IDeviceCallback callback) {
if (callback != null) {
callbacks.register(callback);
}
}
public void unregisterCallback(IDeviceCallback callback) {
if (callback != null) {
callbacks.unregister(callback);
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onDestroy() {
try {
if (mqttClient != null && mqttClient.isConnected()) {
mqttClient.disconnect();
}
} catch (MqttException e) {
e.printStackTrace();
}
callbacks.kill();
super.onDestroy();
}
}
7.4 优化要点
- 前台服务保活:避免被系统杀死
- 自动重连机制:网络断开时自动重连
- 心跳保持:MQTT KeepAlive机制
- 数据持久化:重要数据存储到数据库
- 内存优化:及时释放不用的资源
八、Service ANR分析与避免
8.1 ANR触发条件
- Service的onCreate、onStartCommand、onBind在主线程执行超过20秒
- 前台服务超时20秒,后台服务超时200秒
8.2 ANR日志分析
# 获取ANR日志
adb pull /data/anr/traces.txt
# traces.txt内容示例
----- pid 12345 at 2024-01-01 10:00:00 -----
Cmd line: com.example.app
...
"main" prio=5 tid=1 Native
| group="main" sCount=1 dsCount=0 flags=1 obj=0x74b7f000 self=0x7f8c001200
| sysTid=12345 nice=0 cgrp=default sched=0/0 handle=0x7f8c400000
| state=S schedstat=( 1000000000 200000000 100 ) utm=80 stm=20 core=0 HZ=100
| stack=0x7ff0000000-0x7ff0002000 stackSize=8MB
at java.lang.Thread.sleep(Native method)
at com.example.MyService.onCreate(MyService.java:50)
...
8.3 避免ANR的最佳实践
public class MyService extends Service {
private ExecutorService executor = Executors.newCachedThreadPool();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 不要在主线程执行耗时操作
executor.execute(() -> {
try {
// 耗时操作
performHeavyTask();
} finally {
// 任务完成后停止服务
stopSelf(startId);
}
});
return START_NOT_STICKY;
}
private void performHeavyTask() {
// 网络请求、数据库操作、文件IO等
}
@Override
public void onDestroy() {
executor.shutdown();
super.onDestroy();
}
}
九、性能优化建议
9.1 合理选择启动方式
| 场景 | 推荐方式 |
|---|---|
| 后台任务,不需要交互 | startService + IntentService |
| 需要与Service交互 | bindService |
| 长时间运行 | 前台Service |
| 定时任务 | WorkManager(推荐)或AlarmManager |
9.2 避免内存泄漏
public class MyService extends Service {
// 错误:静态引用导致内存泄漏
private static Context sContext;
// 正确:使用弱引用
private static WeakReference<Context> sContextRef;
@Override
public void onCreate() {
super.onCreate();
// 使用ApplicationContext,避免泄漏Activity
sContextRef = new WeakReference<>(getApplicationContext());
}
}
9.3 进程保活策略
- 前台服务:最可靠的保活方式
- 提升进程优先级:通过startForeground()
- 监听系统广播:在合适时机重启Service
- JobScheduler/WorkManager:系统级任务调度
// 使用WorkManager替代Service(推荐)
public class UploadWorker extends Worker {
public UploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public Result doWork() {
// 执行后台任务
uploadData();
return Result.success();
}
private void uploadData() {
// 上传逻辑
}
}
// 调度任务
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build();
OneTimeWorkRequest uploadWork = new OneTimeWorkRequest.Builder(UploadWorker.class)
.setConstraints(constraints)
.build();
WorkManager.getInstance(context).enqueue(uploadWork);
十、总结
10.1 核心要点
- startService:独立生命周期,适合后台任务
- bindService:绑定生命周期,适合交互场景
- AIDL:跨进程通信的标准方式
- 前台服务:长时间运行的必要条件
- ANR避免:主线程不执行耗时操作
10.2 完整流程对比
| 对比项 | startService | bindService |
|---|---|---|
| 生命周期 | 独立于调用者 | 依赖调用者 |
| 停止方式 | stopService/stopSelf | unbindService |
| 通信方式 | Intent传递数据 | Binder双向通信 |
| 回调方法 | onCreate→onStartCommand | onCreate→onBind |
| 典型场景 | 后台下载、日志上传 | 跨进程调用、实时数据 |
10.3 最佳实践建议
- Android 8.0+优先使用前台服务
- 定时任务优先使用WorkManager
- 避免在Service中执行长时间操作
- 合理管理Service生命周期
- 注意内存泄漏和ANR问题
参考资料
- AOSP源码:https://cs.android.com/
- Android官方文档:https://developer.android.com/guide/components/services
- 《Android进阶解密》 - 刘望舒
- MQTT官方文档:https://mqtt.org/
文章版本:基于Android 10 (API Level 29) AOSP源码
最后更新:2024年
作者声明:本文基于公开AOSP源码和某IoT项目经验(已去敏),不涉及商业机密
更多推荐


所有评论(0)