android service
本篇文章主要讲解bindservice()绑定Service的过程。(Android的版本依旧是26)
通过bindService()绑定一个Service时,最终都是调用的contextWrAPPer的bindService()方法,我们来看下这个方法
@Override
public boolean bindService(intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
上述方法中调用了mBase对象的bindService()方法,mBase的类型是Context,Context的实现类是ContextImpl,我们来看下ContextImpl的bindService()方法
@Override
public boolean bindService(Intent service, ServiceConnection conn,int flags) {
warnIfcallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.gethandler(),
Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
// Keep this in sync with
DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new illegalargumentException("connection is null");
}
if (mPackageInfo != null) {
/*
* sd其实指向的是一个ServiceDispatch.InnerConnection的对象
* 最终调用ServiceConnection的onServiceConnected()方法也是通过这个对象
*/
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new runtimeexception("Not supported in system context");
}
//检查合法性
validateServiceIntent(service);
try {
......
//调用activitymanagerService的bindService()方法
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfneeded(getcontentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
......
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
由上述代码可知,相比较startService()的过程,在调用ActivityManagerService的bindService()方法之前,在bindServiceCommon()方法中多一个获取sd对象,即ServiceDispatch.InnerConnection类的对象的过程,mPackageInfo是LoadedApk类的一个引用,我们来看下mPackageInfo.getServiceDispatcher()中到底做了什么
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) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
/*创建ServiceDispatcher对象
*而在本方法中最终return的sd.getIServiceConnection()的值也是在ServiceDispatcher
*的构造方法中初始化的,稍后的文章中会讲到这一点。
*/
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);
}
//其实最终return的是ServiceDispatcher的内部类InnerConnection对象
return sd.getIServiceConnection();
}
}
上述代码中提到,getServiceDispatcher()方法最终返回的sd.getIServiceConnection()是ServiceDispatcher中的内部类InnerConnection对象,我们先来看一下上述方法最终return的sd.getIServiceConnection()到底是什么
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
可以看到该方法最终return的是一个IServiceConnection对象,看样子像是一个跨进程通信要用的东西,那么这个对象是在哪里创建的呢
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activitythread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
由上述代码可知,mIServiceConnection是在ServiceDispatcher的构造方法中创建的,最终mIServiceConnection引用指向的是以ServiceDispatcher为参数构造的InnerConnection这个内部类的对象。我们来一下InnerConnection这个内部类
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);
}
}
}
InnerConnection继承了IServiceConnection.Stub,看样子应该可以进行跨进程间的通信,内部持有了外部类ServiceDispatcher类的弱引用,代码量比较少,除了构造方法之外,只有一个connected()方法,在这个connected()方法中,获取了外部传递过来的ServiceDispatcher对象,并调用了ServiceDispatcher的connected()方法,我们来看下这个方法
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);
}
}
可以看到connected()方法中会执行RunConnection的run()方法或者doConnected()方法,下面我们来看下RunConnection类
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);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
我们可以看到,在RunConnection类的run()方法中,其实也执行了doConnected()方法,我们来看下这个方法
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
......
/*
* 这个判断逻辑要稍微提一下
* 对于同一个Service,通过bindService()方法bind过一次之后,再次调用
bindService(),不会再调用ServiceConnection的onServiceConnected()方法
* 原因应该就在这里(分析没错的话,应该就是这里)
* 由下面的代码可知,当已经这存在这么一个Service或者说已经bind过的时候,代码到这
里就直接return了
*/
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
......
}
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
上述doConnected()方法中,省略了部分不太重要的代码,剩余的部分应该一目了然,值得一提的是,当我们多次调用bindService()绑定同一个Service的时候,其实只会绑定一次,原因就是在上述的代码中会有判断,如果已经绑定过对应的Service,就不再执行下面的代码,如果是首次调用bindService(),或者绑定不同的Service的时候,会往下执行代码,调用ServiceConnection的onServiceDisconnected()方法或者onBindingDied()方法,取消和旧的Service的连接,最终调用onServiceConnected()方法来建立新的连接。
由于ServiceConnection不能够进行跨进程通信,所以要通过ServiceDispatcher.InnerConnection来保存ServiceConnection的信息,从而进行跨进程通信
好了,关于ServiceDispatch类,以及ServiceDispatch.InnerConnection类的功能大体已经介绍完毕了
下面我们继续回到bindServiceCommon()方法中来,当获取到sd,也就是ServiceDispatch.InnerConnection类的对象之后,就会去执行ActivityManagerService的bindService()方法,即ActivityManager.getService().bindService()。我们来看下这个方法
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String
callingPackage,int userId) throws transactionTooLargeException {
......
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
上述方法会调用ActiveServices的bindServiceLocked()方法
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
......
//根据用户传递进来Intent来检索相对应的服务
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(),Binder.getCallingUid(), userId, true, callerFg,
isBindExternal);
......
ServiceRecord s = res.record;
......
try {
//创建AppBindRecord对象记录着当前ServiceRecord,intent以及发起方的进程信息
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
......
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
/*
* 启动Service,这个过程和startService()一致
* 只不过会区分bindService()和startService(),来执行不同的代码逻辑
*/
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsreviewrequired) != null) {
return 0;
}
}
......
if (s.app != null && b.intent.received) {
/*
* c.conn就是上文中我们提到的ServiceDispatcher.InnerConnection的对象
* 如果Service正在运行,会直接调用他的connected()方法,
* 具体connected()中代码是怎么执行的,上文中已经提到。
*/
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
......
}
// 当第一个app连接到该binding, 且之前已被bind过, 则回调onRebind()方法
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);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
上问中retrieveServiceLocked()方法我就不多做介绍了,有兴趣的朋友可以自己去了解一下,下面我们来简单的看一下s.retrieveAppBindingLocked()方法
public AppBindRecord retrieveAppBindingLocked(Intent intent,
ProcessRecord app) {
Intent.FilterComparison filter = new Intent.FilterComparison(intent);
IntentBindRecord i = bindings.get(filter);
if (i == null) {
i = new IntentBindRecord(this, filter);
bindings.put(filter, i);
}
AppBindRecord a = i.apps.get(app);
if (a != null) {
return a;
}
a = new AppBindRecord(this, i, app);
i.apps.put(app, a);
return a;
}
这个方法很简单,bindings我理解应该是存储了所有已经bind了的Service,这个方法的作用应该就是往bindlings里面put了值,请记住这个bindlings,后面有用。
接下来,我们来看下bindServiceLocked()中的bringUpServiceLocked()方法,这个方法的作用是启动一个Service,同样的,startService()的过程中也会调用这个方法,我在上一篇介绍startService()启动过程的博客中也对这个方法做了详细的介绍,因为这个方法比较重要,本文再对这个方法做一些讲解,与上篇博客不同的是,针对该方法,上篇博客是针对startService()来介绍的这个方法,而本篇博客是针对bindService()介绍的该方法
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
/*
* 个人理解:
* 由本方法的参数可知,r是ServiceRecord的对象,ServiceRecord代表着一个Service记录
* 联系整个Service的启动过程可知:
* 首次调用bindService()启动一个Service时候,r.app应该为null,下面的if判断不成立
* 如果不是首次调用bindService()方法,则下面的if判断成立,调用
sendServiceArgsLocked()方法,然后return,
* 针对bindService()这个过程,在sendServiceArgsLocked()方法的开始处就已经return了,
并没有往下执行,可以说sendServiceArgsLocked()方法和bindService()这个过程无关
* 此处不对sendServiceArgsLocked()方法做过多解释,因为该方法主要是针对startService()
这个过程的,稍后下文中会讲到
*/
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
......
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
......
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode,
mAm.mProcessStats);
//执行realStarServiceLocked(),开始正式执行Servcie的启动过过程
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
......
}
}
} else {
......
}
......
return null;
}
上述方法的注释中已经描述的很清楚了,下面我简单的解释一下为什么bindService()的过程中sendServiceArgsLocked()方法在刚开始处就return了,我们来简单看下sendServiceArgsLocked()方法的代码
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
final int N = r.pendingStarts.size();
if (N == 0) {
return;
}
......
}
如果我理解的没错的话,原因就是,在sendServiceArgsLocked()方法的开始处,r.pendingStarts.size() = 0,因为pendingStarts是在startService()的过程中add值的,有兴趣的朋友可以自己查看一下源码,我就不针对这个小问题过多的解释了,之前也说过,代码也是人写的,过多的纠结细节问题,只能是只见树木,不见森林。
好了,我们回到bringUpServiceLocked()中来,接下来就会执行·realStartServiceLocked(),这个方法上篇博客也已经介绍过了,下面我们再回顾一下
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
......
/* r是ServiceRecord的对象,对应了一个Service
* r.app是ProcessRecord的对象,对应了app所在的进程
* 首次调用bindService()时,会执行本方法
* 而r.app = app的作用相当于把Service与进程关联起来
*/
r.app = app;
......
try {
......
//app.thread其实就是ActivityThread中ApplicationThread类的对象,
//调用ApplicationThread的scheduleCreateService()方法
//顾名思义,该方法就最终调用的应该就是Service的onCreate()方法
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
......
} catch (DeadObjectException e) {
......
} finally {
......
}
/*
* 该方法是通过bindService()绑定Service的时候才去真正的调用,从而调用onBind()方法
* 当通过startService()方法来开启一个Service的时候,该方法内部的逻辑不成立
* 稍后会介绍这个方法的内容
*/
requestServiceBindingsLocked(r, execInFg);
......
/* 该方法通过startService()开启一个Service的时候会去真正的调用,从而调用
onStartCommon()方法
* 当通过bindService()来绑定一个Service的时候,该方法的内部逻辑不成立
* 上一篇博客中已经对该方法做了详细的介绍,因为bindService()基本不涉及到该方法,本文
对该方法不再做介绍
*/
sendServiceArgsLocked(r, execInFg, true);
......
}
下面我们先看下上述方法中提到的app.thread.scheduleCreateService()方法,其实就是ActivityThread中ApplicationThread的scheduleCreateService()方法,看下Service的onCreate()是怎么执行的,其实startService()的这个过程和bindService()的这个过程基本是一样的,为了文章的完整性,我从上篇博客把这一小部分的代码copy过来了,算是回顾一下吧(真心有强迫症~_~)
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);
}
如果看过我前几篇Activity启动相关博客的朋友,对上述方法这种类型的代码结构应该不陌生,基本上和Activity启动过程中调用的ApplicationThread方法都是一致的,调用sendMessage()方法,通过Handler发送一个消息,然后在Handler的handleMessage()方法中去处理这个消息,这一小块的相关代码我就不详细说了,也比较简单,不过还是把代码粘贴出来。
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
下面我们来看下在mH这个Handler的handleMessage()方法中是怎么处理这个事件的
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......
}
......
}
由上述方法可知,在Handler的handleMessage()方法中,处于这个事件时,回去调用handleCreateService()方法,我们来看下这个方法
private void handleCreateService(CreateServiceData data) {
......
//通过getPackageInfoNoCheck()方法获取一个LoadedApk的对象
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//通过反射的方式,调用ClassLoader的loadClass()方法,创建一个Service对象
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newinstance();
} catch (Exception e) {
......
}
try {
......
//创建一个ContextImpl对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//获取Application对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
//调用Service的attach()方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用Service的onCreate()方法
service.onCreate();
mServices.put(data.token, service);
......
} catch (Exception e) {
......
}
}
上述方法的注释中已经解释的很清楚了,我就不多做解释了,不过需要提一点的是,在上述方法中有两个方法getPackageInfoNoCheck()以及packageInfo.makeApplication()这个两个方法,getPackageInfoNoCheck()方法获取的是一个LoadedApk对象,LoadedApk对象是apk文件在内存中的表示,apk文件的相关信息,比如apk文件中的资源,甚至是代码里面的Activity、Service等组件的信息都可以通过此对象获取,而且packageInfo.makeApplication()方法获取的是一个Application对象,若Application已经创建过,则直接return之前创建的Application对象,对这两个方法,这里我就简单的描述一下,就不贴出代码解释了,有想了解的朋友,可以看一下我之前的一篇博客 Android Activity启动(一) Application创建的过程以及原理分析,也涉及到相关的内容,讲解的也比较详细。到此为止,Service的onCreate()方法的执行流程已经介绍完毕了。
我们再次回到realStartServiceLocked()中来,总结一下该方法中app.thread.scheduleCreateService()方法,调用了ApplicationThread的scheduleCreateService()方法,通过Handler处理事件,调用了ActivityThread的handleCreateService()方法,通过反射的方式获取Service的对象,然后依次调用Service的attach()方法和onCreate()方法。
下面我们来继续看下realStartServiceLocked()方法中的app.thread.scheduleCreateService()之后执行的requestServiceBindingLocked()方法
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
//在startService()的过程中bindings.size() = 0,不会执行for循环
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
在上述方法中会遍历bindings,从而调用requestServiceBindingLocked()方法,这个方法最终才会去调用Service的onBind()方法,而bindings我在上文中已经加了红色字体标注,只在bindService()中会add值,在startService()过程中并不会对其添加值,这也是为什么在startService()和bindService()执行的方法都是一样的,但是结果却不一样。
我们来看下requestServiceBindingLocked()方法
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {
......
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//调用ApplicationThread的scheduleBindService()
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
......
} catch (RemoteException e) {
......
}
}
return true;
}
在上述方法中,调用了ApplicationThread的scheduleBindService(),我们来看下这个方法
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;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + "
uid="+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
......
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......
}
......
}
很明显,ApplicationThread的scheduleBindService()方法中,也是发送了一个消息,最终在Handler的handleMessage()中处理了这个消息,调用了handleBindService()方法
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//调用Service的onBind()方法
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
//调用Service的onRebind()方法
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
......
}
}
}
我们可以看到在handleBindService()方法中调用了Service的onBind()方法,然后通过ActivityManager.getService()获取到ActivityManagerService的对象,调用其publishService()方法,我们来看一下这个方法
public void publishService(IBinder token, Intent intent, IBinder service) {
......
synchronized(this) {
......
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
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;
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
......
try {
/*
* 关键代码,下面的方法最终会回调ServiceConnection的
onServiceConnected()方法
*/
c.conn.connected(r.name, service, false);
} catch (Exception e) {
......
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
在上述代码中,c.conn.connected()方法比较重要,其中c.conn就是上文中提到的ServiceDispatch.InnerConnection的对象,然后调用它的connected()方法,关于connected()方法上文中已经有了比较详细的介绍,这里就不多提了。
到此为止,我们关于bindService()的启动过程已经介绍完毕了,下面我来总结一下:
当我们调用bindService()方法的时候,
(1)会调用ContextImpl的bindService()方法,然后获取到一个ServiceDispatch.InnerConnection的对象,可以跨进程通信,
(2)调用ActivityManagerService的bindService()方法,然后调用bringUpServiceLocked()方法,这个方法在startService()和bindService()的过程中都会调用
(3)执行realStartServiceLocked()方法,这个方法中通过调用ActivityThread中ApplicationThread的scheduleCreateService()方法,真正执行了Service的创建过程,即onCreate()
(4)调用了requestServiceBindingsLocked()方法,在这个方法中,会去调用ActivityThread中ApplicationThread的scheduleBindService()方法来执行Service的bind过程,即onBind()
(5)然后调用ActivityManagerService的publishService(),然后调用publishServiceLocked()方法,在这个方法中会调用ServiceDispatch.InnerConnection的connected()方法,最终回调ServiceConnection的onServiceConnected()方法。
(额,写完了,篇幅有点长,有出错的地方欢迎批评指正,谢谢!!!)
文章最后发布于: 2019-03-13 21:14:13
相关阅读
Hbuilder android 在线更新功能 后端获取最新版本号和
写这个博文的意义在于,做了一个使用纯h5网页的东西,然后想用hbuilder在外面包一层,这样就能android和ios都能同时使用,hb
准备工作
专题地址:http://www.apkbus.com/heima/ 黑马Android入门到精通 视频教程 01.什么是3G? 03_an
sc20_gpio.c ``` #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #inc
在我们开发系统级的App时,很有可能就会用persistent属性。当在AndroidManifest.xml中将persistent属性设置为true时,那么该App就会