我们知道调用Context的bindService方法即可绑定一个Service,而ContextImpl是Context的实现类。那接下来就从源码的角度分析Service的绑定过程。

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

@Overridepublic boolean bindService(Intent service, ServiceConnection conn,        int flags) {    warnIfCallingFromSystemProcess();    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),            Process.myUserHandle());}

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

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler        handler, UserHandle user) {    IServiceConnection sd;    if (conn == null) {        throw new IllegalArgumentException("connection is null");    }    if (mPackageInfo != null) {        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);        int res = ActivityManagerNative.getDefault().bindService(            mMainThread.getApplicationThread(), getActivityToken(), service,            service.resolveTypeIfNeeded(getContentResolver()),            sd, flags, 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();    }}

在上述代码中,调用了mPackageInfo(LoadedApk对象)的getServiceDispatcher方法。从getServiceDispatcher方法的名字可以看出是获取一个“服务分发者”。其实是根据这个“服务分发者”获取到一个Binder对象的。

到了这里先总结一下:调用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方法即可,如下:

public int bindService(IApplicationThread caller, IBinder token, Intent service,        String resolvedType, IServiceConnection connection, int flags, String callingPackage,        int userId) throws TransactionTooLargeException {    enforceNotIsolatedCaller("bindService");    // Refuse possible leaked file descriptors    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) {        return mServices.bindServiceLocked(caller, token, service,                resolvedType, connection, flags, callingPackage, userId);    }}

经过一系列的方法调用 调用了realStartServiceLocked方法,真正去启动Service了。

private final void realStartServiceLocked(ServiceRecord r,        ProcessRecord app, boolean execInFg) throws RemoteException {      //代码省略     app.thread.scheduleCreateService(r, r.serviceInfo,              mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),        app.repProcState);       r.postNotification();       created = true;     //代码省略    requestServiceBindingsLocked(r, execInFg);    updateServiceClientActivitiesLocked(app, null, true);    // If the service is in the started state, and there are no    // pending arguments, then fake up one so its onStartCommand() will    // be called.    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),                null, null));    }    sendServiceArgsLocked(r, execInFg, true);//代码省略}

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

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)        throws TransactionTooLargeException {    for (int i=r.bindings.size()-1; i>=0; i--) {        IntentBindRecord ibr = r.bindings.valueAt(i);        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {            break;        }    }}

进过一系列的方法调用 实现绑定

当Service回调onBind方法,其实还没有结束,会转到ActivityManagerService,然后又会在ActiveServices的publishServiceLocked方法中,从ConnectionRecord中取出InnerConnection对象。有了InnerConnection对象后,就回调了它的connected。在InnerConnection的connected方法中,又会调用ServiceDispatcher的connected方法,在ServiceDispatcher的connected方法向主线程扔了一个消息,切换到了主线程,之后就在主线程中回调了客户端传进的ServiceConnected对象的onServiceConnected方法。

参考文章

更多相关文章

  1. Android监听返回键、Menu键、Home键、
  2. Android(安卓)Values文件作用及使用方法
  3. android动态更改menu元素
  4. 安卓修改屏幕超时后,系统不进入休眠的方法。
  5. LeakCanary源码解析之检测篇
  6. 初学Android的一些注意事项
  7. Android(安卓)调用摄像头拍照 以及 从相册中选择照片
  8. 【Android】项目常用功能集锦(一)
  9. Android(安卓)Thread第二次Thread.start()报错的疑问

随机推荐

  1. Android(安卓)OpenGL例子学习
  2. 在AndroidManifest.xml文件中的android:w
  3. android获取短信所有内容
  4. Android: 系统默认音量
  5. Android逆向分析常用网站
  6. Android中常用的Intent.Action整理
  7. android(2.0以后版本) 中读取联系人和通
  8. 更新SDK后eclipse报错This Android(安卓)
  9. Android(安卓)NDK 开发
  10. android之android.os.NetworkOnMainThrea