您好,登录后才能下订单哦!
这篇文章主要介绍了Android Service启动绑定流程是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android Service启动绑定流程是什么文章都会有所收获,下面我们一起来看看吧。
启动一个Service
,通常在Activity
调用startService
来启动。
@Override public ComponentName startService(Intent service) { return startServiceCommon(service, false, mUser); }
startServiceCommon
检查intent
内容是否合法,然后做一些离开当前进程的准备操作。调用 ActivityManager.getService()
获得AMS
的本地引用,并调用其startService
函数。
也就是说通过Binder
机制跨进程通信调用了AMS
的startService
函数。
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { //检查intent 的compant和package是否合法 validateServiceIntent(service); ... ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier()); ... return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
通过 ActivityManager.getService()
的实现。
@UnsupportedAppUsage public static IActivityManager getService() { return IActivityManagerSingleton.get(); } @UnsupportedAppUsage private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
AMS.startService
函数获取调用Pid
和Uid
,然后调用ActiveService
的startServiceLocked
函数。
@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, String callingFeatureId, int userId) throws TransactionTooLargeException { ... synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
ActiveService.startServiceLock
函数,对一些合法性的检查,例如前台Service
的权限、限制性后台Service
进行延迟运行(standby)
。并将要启动的信息封装成ServiceRecord
。然后调用了startServiceInnerLocked
函数。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, callingPackage, callingFeatureId, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { final boolean callerFg; if (caller != null) { //获取调用Service的应用程序进程描述 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { ... } callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; } else { callerFg = true; } //检索ServiceRecord,包括同应用和其他应用 ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); ... //要启动的ServiceRecord ServiceRecord r = res.record; ... 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)); ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); ... return cmp; }
调用了bringUpServiceLocked
函数,会将ServiceRecord
添加到ServiceMap
类型的smap
集合,进行缓存。
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { r.callStart = false; ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); ... return r.name; }
分析一:首次启动Service
时,在执行bringUpServiceLocked
函数,ServiceRecord
是属于新创建的,而非从AMS
的缓存mServices
中检索而来,所以此时的ServiceRecord
的ProcessRecord
类型app
和IApplicationThread
类型thread
都是null。只有启动过后的ServiceRecord
才有值,才会执行sendServiceArgsLocked
函数,重复调用Service
的生命周期onStartCommand
,而不调用onCreate
函数。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { //分析一:未启动过的ServiceRecord两者都是null,重复启动会执行该函数, //会重复调用service的onStartCommand函数。 if (r.app != null && r.app.thread != null) { sendServiceArgsLocked(r, execInFg, false); return null; } ... 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) { ////通过AMS获取service所在进程的ProcessRecord。ProcessList=>MyProcessMap=》会缓存已创建过进程的ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); //启动服务 realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e); } } } //如果service所在的进程未启动,通过AMS启动该进程,可以参考应用进程的启动流程 if (app == null && !permissionsReviewRequired) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {; bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc = app; } } //等待进程启动完毕重启启动 if (!mPendingServices.contains(r)) { mPendingServices.add(r); } ... return null; }
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //将ProcessRecord设置给ServiceRecord r.setProcess(app); //登记当ServiceRecord到ProcessRecordd的数组mServices,表示Service已经启动(实际未启动) final boolean newService = app.startService(r); boolean created = false; try { ... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); ... } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app, "Died when creating service"); throw e; } //会调用Service的onStartCommand函数 sendServiceArgsLocked(r, execInFg, true); ... }
通过ProcessRecord
对象的IApplicationThread
引用,通过Binder
机制调用了应用程序的ApplicationThread
的scheduleCreateService
函数。
将ServiceInfo
等相关信息封装到CreateServiceData
中,并发送给ActivityThread
的H
类型的mH
对象。
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); }
调用了ActivityThread
的handleCreateService
函数。
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 { //创建Service的上下问文 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //获取当前应用Applcation对象 Application app = packageInfo.makeApplication(false, mInstrumentation); //通过反射创建Service对象 java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); //初始化资源 context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //context 与service相互绑定 context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //调用Service的生命周期onCreate函数,意味Service创建完毕 service.onCreate(); //缓存Service mServices.put(data.token, service); 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); } } }
通过ContextImpl.createAppContext
创建Service
的上下文context
,通过packageInfo.getAppFactory().instantiateService
反射获得当前Service
对象service
,将context
与service
相互绑定。然后调用service.onCreate
。至此,Service
创建完毕。
public boolean bindService(Intent service, ServiceConnection conn, int flags) { //系统进程调用绑定服务或发送广播都会发出警告 warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); }
在分析一,主要判断入参Executor executor
或UserHandle user
哪个为null
,总有一个为null
,但最终都是调用了LoadedApk
的getServiceDispatcherCommon
函数来获取ServiceDispathcer
类型sd。影响只是回调代码是在主线程执行,还是线程池。这里传入ActivityThread
的H
对象,意味着后续连接成功回调onServiceConnected
是在主线程。
分析二:通过Binder机制调用AMS
的bindIsolatedService
函数。
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser. IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (handler != null && executor != null) { throw new IllegalArgumentException("Handler and Executor both supplied"); } if (mPackageInfo != null) { if (executor != null) {//分析一:无论哪个分支,都是获得ServiceConnect的本地引用sd,两者最终都是 //调用LoadedApk的getServiceDispatcherCommon sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { //正常使用走这个分支 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } } else { throw new RuntimeException("Not supported in system context"); } //检查compant and package is null ? 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.bindIsolatedService int res = ActivityManager.getService().bindIsolatedService( 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(); } }
IServiceConnection
连接的创建会先从缓存中获取,避免每次都要新建。分析一:通过executor
或handler
创建ServiceDispatcher
类型的sd
,含有静态内部类InnerConnection
的引用mIServiceConnection
。继承自IServiceConnection.Stub
,也就是InnerConnection
是实现者,远程调用代理在其他进程,例如SystemServer
进程中的ActiveService
。
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) { //分析一:通过executor或handler创建ServiceDispatcher if (executor != null) { sd = new ServiceDispatcher(c, context, executor, flags); } else { sd = new ServiceDispatcher(c, context, handler, flags); } if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); if (map == null) { map = new ArrayMap<>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler, executor); } return sd.getIServiceConnection(); } }
AMS
经过两次重载函数bindIsolatedService
调用,简单检查相关合法性。然后调用ActiveService
类型的mService
的bindServiceLocked
函数。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { //发起绑定service的app进程描述 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); ... ServiceLookupResult res = retrieveServiceLocked(service, instanceName, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant); ... ServiceRecord s = res.record; ... //描述Service和应用程序进程之间的关联,内部维护Service、进程、IntentFilter以及所有绑定信息。 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //描述应用程序与service建立的一次通信(绑定) ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent, callerApp.uid, callerApp.processName, callingPackage); IBinder binder = connection.asBinder(); s.addConnection(binder, c); b.connections.add(c); if (activity != null) { activity.addConnection(c); } b.client.connections.add(c); c.startAssociationIfNeeded(); ... //启动Service,可以参考Service的启动 if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } ... //表示Service已启动,且已返回binder,可以通过binder访问接口 if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. 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); } //第一个绑定该Service的进程,且要重绑 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); } ... }
AppBindRecord
描述应用程序进程和Service
的关联,包括谁绑定了Service
的ProcessRecord
,绑定信息IntentBindRecord
,当前服务ServiceRecord
,当前应用进程的所有连接记录connections
。
调用了ApplicationThread
的scheduleBindService
函数。
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { ... r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState()); ... }
将数据封装 BindServiceData
,发送个ActivityThread
的H类型的mH
处理。
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; sendMessage(H.BIND_SERVICE, s); }
case BIND_SERVICE: handleBindService((BindServiceData)msg.obj);
handleBindService
函数有两个分支,即是否重新绑定。
如果当前进程第一个与Service
绑定,且调用过了onUbBinder
方法,那么这里的data.rebind
将为true
,直接执行Service
的onRebind
函数即可。另外一种就是没有绑定过,那么需要执行Service
的onBind
函数。然后还要执行AMS
的publishService
函数。
private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { ... try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManager.getService().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ... } }
public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
分析一:可见在第4步bindServiceLocked
函数,IntentBindRecord
对象的属性binder
、requested
、received
都是false
。
在ServiceRecord
的所有连接记录connections
中,通过intent
查找对应之前已经保存的ConnectionRecord
,并调用其IServiceConnection
的connected
函数。
在第2步的时候调用bindServiceCommon
函数时,会创建ServiceDispatcher
时,内部持有InnerConnection
实例,这里的IServiceConnection
代理引用指向该InnerConnection
实例,这里会调用其connected
函数。
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) {//分析1 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 { 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); } }
private static class InnerConnection extends IServiceConnection.Stub { @UnsupportedAppUsage 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); } } }
这里调用了 mActivityThread.post(new RunConnection(name, service, 0, dead))
,执行RunConnection
的run
函数。这里的话run函数执行代码又回到了应用进程的主线程。
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)); } else { doConnected(name, service, dead); } }
RunConnection
是ServiceDispatcher
的内部类,这里执行SD
的doConnected
函数。
public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } }
这里调用了ServiceConnection
对象的onServiceConnected
函数,也就是我们发起绑定,调用context.bindService
的参数。
public void doConnected(ComponentName name, IBinder service, boolean dead) { ... mConnection.onServiceConnected(name, service); ... }
到此,Service
的绑定流程分析完毕。
在第一节Service的启动流程最后函数调用了ActivityThread
的handleCreateService
函数。
private void handleCreateService(CreateServiceData data) { unscheduleGcIdler(); //应用的描述信息 LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //分析一 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); Application app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //分析二 context.setOuterContext(service); //分析三 service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); mServices.put(data.token, service); 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); } } }
分析一:通过ContextImpl
的静态函数createAppContext
返回了一个ContextImpl
类型的context
。createAppContext
又调用了重载函数createAppContext
。直接新建了ContextImpl实例context,构造函数传递了ActivityThread类型的mainThread和LoadedApk类型的packageInfo。并给context设置了资源环境和是否Syetem属性。
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { return createAppContext(mainThread, packageInfo, null); } static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo, String opPackageName) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null, 0, null, opPackageName); context.setResources(packageInfo.getResources()); context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context); return context; }
ContextImpl
类有一个Context
类型的mOuterContext
属性,在构造函数时指向了自己。
回到handleCreateService
函数的分析二,在创建好Service
对象service
之后,将service
作为参数传递给了context.setOuterContext
函数。Service
本身继承自ContextWrapper
,ContextWrapper
又是Context
的子类。这时候的setOuterContext
函数将service
设置给了context
的mOuterContext
属性。意味着当前上下文context
持有当前新建的service
引用。
在分析三,调用了service.attach
函数,context
并作为第一个参数被传入。attach
函数又调用了attachBaseContext
函数。
public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) { attachBaseContext(context); mThread = thread; mClassName = className; mToken = token; mApplication = application; mActivityManager = (IActivityManager)activityManager; mStartCompatibility = getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR; setContentCaptureOptions(application.getContentCaptureOptions()); }
attachBaseContext
调用了父类ContextWrapper
的attachBaseContext
函数
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); if (newBase != null) { newBase.setContentCaptureOptions(getContentCaptureOptions()); } }
ContextWrapper
将一路传递过来的上下文base
设置给你了mBase
属性。
protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; }
也就是说,我们在启动Service
时,会同时创建Service
的上下文context
,并将其存储到Service的父类ContextWrapper
的mBases
属性中,同时context
也会有当前Service引用,存储在mOuterContext
变量中。
关于“Android Service启动绑定流程是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Android Service启动绑定流程是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。