Android Service的绑定过程.docx

上传人:b****6 文档编号:3480890 上传时间:2022-11-23 格式:DOCX 页数:16 大小:126.23KB
下载 相关 举报
Android Service的绑定过程.docx_第1页
第1页 / 共16页
Android Service的绑定过程.docx_第2页
第2页 / 共16页
Android Service的绑定过程.docx_第3页
第3页 / 共16页
Android Service的绑定过程.docx_第4页
第4页 / 共16页
Android Service的绑定过程.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

Android Service的绑定过程.docx

《Android Service的绑定过程.docx》由会员分享,可在线阅读,更多相关《Android Service的绑定过程.docx(16页珍藏版)》请在冰豆网上搜索。

Android Service的绑定过程.docx

AndroidService的绑定过程

AndroidService的绑定过程

通常我们使用Service都要和它通信,当想要与Service通信的时候,那么Service要处于绑定状态的。

然后客户端可以拿到一个Binder与服务端进行通信,这个过程是很自然的。

那你真的了解过Service的绑定过程吗?

为什么可以是Binder和Service通信?

同样的先看一张图大致了解一下,灰色背景框起来的是同一个类的方法,如下:

我们知道调用Context的bindService方法即可绑定一个Service,而ContextImpl是Context的实现类。

那接下来就从源码的角度分析Service的绑定过程。

当然是从ContextImpl的bindService方法开始,如下:

@Override

publicbooleanbindService(Intentservice,ServiceConnectionconn,

intflags){

warnIfCallingFromSystemProcess();

returnbindServiceCommon(service,conn,flags,mMainThread.getHandler(),

Process.myUserHandle());

}

在bindService方法中又会转到bindServiceCommon方法,将Intent,ServiceConnection对象传进。

那就看看bindServiceCommon方法的实现。

privatebooleanbindServiceCommon(Intentservice,ServiceConnectionconn,intflags,Handler

handler,UserHandleuser){

IServiceConnectionsd;

if(conn==null){

thrownewIllegalArgumentException("connectionisnull");

}

if(mPackageInfo!

=null){

sd=mPackageInfo.getServiceDispatcher(conn,getOuterContext(),handler,flags);

}else{

thrownewRuntimeException("Notsupportedinsystemcontext");

}

validateServiceIntent(service);

try{

IBindertoken=getActivityToken();

if(token==null&&(flags&BIND_AUTO_CREATE)==0&&mPackageInfo!

=null

&&mPackageInfo.getApplicationInfo().targetSdkVersion

flags|=BIND_WAIVE_PRIORITY;

}

service.prepareToLeaveProcess(this);

intres=ActivityManagerNative.getDefault().bindService(

mMainThread.getApplicationThread(),getActivityToken(),service,

service.resolveTypeIfNeeded(getContentResolver()),

sd,flags,getOpPackageName(),user.getIdentifier());

if(res<0){

thrownewSecurityException(

"Notallowedtobindtoservice"+service);

}

returnres!

=0;

}catch(RemoteExceptione){

throwe.rethrowFromSystemServer();

}

}

在上述代码中,调用了mPackageInfo(LoadedApk对象)的getServiceDispatcher方法。

从getServiceDispatcher方法的名字可以看出是获取一个“服务分发者”。

其实是根据这个“服务分发者”获取到一个Binder对象的。

那现在就看到getServiceDispatcher方法的实现。

publicfinalIServiceConnectiongetServiceDispatcher(ServiceConnectionc,

Contextcontext,Handlerhandler,intflags){

synchronized(mServices){

LoadedApk.ServiceDispatchersd=null;

ArrayMapmap=mServices.get(context);

if(map!

=null){

sd=map.get(c);

}

if(sd==null){

sd=newServiceDispatcher(c,context,handler,flags);

if(map==null){

map=newArrayMap();

mServices.put(context,map);

}

map.put(c,sd);

}else{

sd.validate(context,handler);

}

returnsd.getIServiceConnection();

}

}

从getServiceDispatcher方法的实现可以知道,ServiceConnection和ServiceDispatcher构成了映射关系。

当存储集合不为空的时候,根据传进的key,也就是ServiceConnection,来取出对应的ServiceDispatcher对象。

当取出ServiceDispatcher对象后,最后一行代码是关键,

returnsd.getIServiceConnection();

调用了ServiceDispatcher对象的getIServiceConnection方法。

这个方法肯定是获取一个IServiceConnection的。

IServiceConnectiongetIServiceConnection(){

returnmIServiceConnection;

}

那么mIServiceConnection是什么?

现在就可以来看下ServiceDispatcher类了。

ServiceDispatcher是LoadedApk的内部类,里面封装了InnerConnection和ServiceConnection。

如下:

staticfinalclassServiceDispatcher{

privatefinalServiceDispatcher.InnerConnectionmIServiceConnection;

privatefinalServiceConnectionmConnection;

privatefinalContextmContext;

privatefinalHandlermActivityThread;

privatefinalServiceConnectionLeakedmLocation;

privatefinalintmFlags;

privateRuntimeExceptionmUnbindLocation;

privatebooleanmForgotten;

privatestaticclassConnectionInfo{

IBinderbinder;

IBinder.DeathRecipientdeathMonitor;

}

privatestaticclassInnerConnectionextendsIServiceConnection.Stub{

finalWeakReferencemDispatcher;

InnerConnection(LoadedApk.ServiceDispatchersd){

mDispatcher=newWeakReference(sd);

}

publicvoidconnected(ComponentNamename,IBinderservice)throwsRemoteException{

LoadedApk.ServiceDispatchersd=mDispatcher.get();

if(sd!

=null){

sd.connected(name,service);

}

}

}

privatefinalArrayMapmActiveConnections

=newArrayMap();

ServiceDispatcher(ServiceConnectionconn,

Contextcontext,HandleractivityThread,intflags){

mIServiceConnection=newInnerConnection(this);

mConnection=conn;

mContext=context;

mActivityThread=activityThread;

mLocation=newServiceConnectionLeaked(null);

mLocation.fillInStackTrace();

mFlags=flags;

}

//代码省略

}

先看到ServiceDispatcher的构造方法,一个ServiceDispatcher关联一个InnerConnection对象。

而InnerConnection呢?

,它是一个Binder,有一个很重要的connected方法。

至于为什么要用Binder,因为与Service通信可能是跨进程的。

好,到了这里先总结一下:

调用bindService方法绑定服务,会转到bindServiceCommon方法。

在bindServiceCommon方法中,会调用LoadedApk的getServiceDispatcher方法,并将ServiceConnection传进,根据这个ServiceConnection取出与其映射的ServiceDispatcher对象,最后调用这个ServiceDispatcher对象的getIServiceConnection方法获取与其关联的InnerConnection对象并返回。

简单点理解就是用ServiceConnection换来了InnerConnection。

现在回到bindServiceCommon方法,可以看到绑定Service的过程会转到ActivityManagerNative.getDefault()的bindService方法,其实从抛出的异常类型RemoteException也可以知道与Service通信可能是跨进程的,这个是很好理解的。

而ActivityManagerNative.getDefault()是ActivityManagerService,那么继续跟进ActivityManagerService的bindService方法即可,如下:

publicintbindService(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,IServiceConnectionconnection,intflags,StringcallingPackage,

intuserId)throwsTransactionTooLargeException{

enforceNotIsolatedCaller("bindService");

//Refusepossibleleakedfiledescriptors

if(service!

=null&&service.hasFileDescriptors()==true){

thrownewIllegalArgumentException("FiledescriptorspassedinIntent");

}

if(callingPackage==null){

thrownewIllegalArgumentException("callingPackagecannotbenull");

}

synchronized(this){

returnmServices.bindServiceLocked(caller,token,service,

resolvedType,connection,flags,callingPackage,userId);

}

}

在上述代码中,绑定Service的过程转到ActiveServices的bindServiceLocked方法,那就跟进ActiveServices的bindServiceLocked方法瞧瞧。

如下:

intbindServiceLocked(IApplicationThreadcaller,IBindertoken,Intentservice,

StringresolvedType,finalIServiceConnectionconnection,intflags,

StringcallingPackage,finalintuserId)throwsTransactionTooLargeException{

//代码省略

ConnectionRecordc=newConnectionRecord(b,activity,

connection,flags,clientLabel,clientIntent);

IBinderbinder=connection.asBinder();

ArrayListclist=s.connections.get(binder);

if(clist==null){

clist=newArrayList();

s.connections.put(binder,clist);

}

clist.add(c);

//代码省略

if((flags&Context.BIND_AUTO_CREATE)!

=0){

s.lastActivity=SystemClock.uptimeMillis();

if(bringUpServiceLocked(s,service.getFlags(),callerFg,false,

permissionsReviewRequired)!

=null){

return0;

}

}

//代码省略

return1;

}

将connection对象封装在ConnectionRecord中,这里的connection就是上面提到的InnerConnection对象。

这一步很重要的。

然后调用了bringUpServiceLocked方法,那么就探探这个bringUpServiceLocked方法,

privateStringbringUpServiceLocked(ServiceRecordr,intintentFlags,booleanexecInFg,

booleanwhileRestarting,booleanpermissionsReviewRequired)

throwsTransactionTooLargeException{

//代码省略

if(app!

=null&&app.thread!

=null){

try{

app.addPackage(r.appInfo.packageName,r.appInfo.versionCode,mAm.mProcessStats);

realStartServiceLocked(r,app,execInFg);

returnnull;

}catch(TransactionTooLargeExceptione){

throwe;

}catch(RemoteExceptione){

Slog.w(TAG,"Exceptionwhenstartingservice"+r.shortName,e);

}

//Ifadeadobjectexceptionwasthrown--fallthroughto

//restarttheapplication.

}

//代码省略

returnnull;

}

可以看到调用了realStartServiceLocked方法,真正去启动Service了。

那么跟进realStartServiceLocked方法探探,如下:

privatefinalvoidrealStartServiceLocked(ServiceRecordr,

ProcessRecordapp,booleanexecInFg)throwsRemoteException{

//代码省略

app.thread.scheduleCreateService(r,r.serviceInfo,

mApatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app.repProcState);

r.postNotification();

created=true;

//代码省略

requestServiceBindingsLocked(r,execInFg);

updateServiceClientActivitiesLocked(app,null,true);

//Iftheserviceisinthestartedstate,andthereareno

//pendingarguments,thenfakeuponesoitsonStartCommand()will

//becalled.

if(r.startRequested&&r.callStart&&r.pendingStarts.size()==0){

r.pendingStarts.add(newServiceRecord.StartItem(r,false,r.makeNextStartId(),

null,null));

}

sendServiceArgsLocked(r,execInFg,true);

//代码省略

}

这里会调用app.thread的scheduleCreateService方法去创建一个Service,然后会回调Service的生命周期方法,然而绑定Service呢?

在上述代码中,找到一个requestServiceBindingsLocked方法,从名字看是请求绑定服务的意思,那么就是它没错了。

privatefinalvoidrequestServiceBindingsLocked(ServiceRecordr,booleanexecInFg)

throwsTransactionTooLargeException{

for(inti=r.bindings.size()-1;i>=0;i--){

IntentBindRecordibr=r.bindings.valueAt(i);

if(!

requestServiceBindingLocked(r,ibr,execInFg,false)){

break;

}

}

}

咦,我再按住Ctrl+鼠标左键,点进去requestServiceBindingLocked方法。

如下:

privatefinalbooleanrequestServiceBindingLocked(ServiceRecordr,IntentBindRecordi,

booleanexecInFg,booleanrebind)throwsTransactionTooLargeException{

if(r.app==null||r.app.thread==null){

//Ifserviceisnotcurrentlyrunning,can'tyetbind.

returnfalse;

}

if((!

i.requested||rebind)&&i.apps.size()>0){

try{

bumpServiceExecutingLocked(r,execInFg,"bind");

r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

r.app.thread.scheduleBindService(r,i.intent.getIntent(),rebind,

r.app.repProcState);

if(!

rebind){

i.requested=true;

}

i.hasBound=true;

i.doRebind=false;

}

//代码省略

returntrue;

}

r.app.thread调用了scheduleBindService方法来绑定服务,而r.app.thread是Applicat

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 交通运输

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1