Android组件管理框架—后台服务Service之bindService方式启动流程(Android P)

本文详细解析了在Android P中,如何通过bindService启动后台服务Service的过程,涉及ContextWrapper、ContextImpl、ActivityThread、ActivityManagerService等多个组件的交互,强调了ServiceDispatcher和InnerConnection在服务绑定过程中的关键作用。
摘要由CSDN通过智能技术生成

一 前言

        通过startservice来启动一个service,通常该service是无法返回结果的(这也是与bindservice的区别之一),服务开启, 这个服务和开启他的调用者之间就没有任何的关系了,调用者的生命周期和它的生命周期也没有关系(所以,service在任务完成的时调用stopSelf或stopsService来结束该服务)。

       通过bindservice来和service绑定,绑定后可以和service交互,发送请求,得到结果甚至执行IPC通信。由于调用者和绑定者绑在一起,调用者一旦退出该服务也就终止了。

       可以先看Android组件管理框架—后台服务Service之startService方式启动流程(Android P)

 

二 图示调用流程

图示调用流程展示的是主要调用流程。

 

三 代码具体流程

调用者调用bindService后将会调用下面的方法。

1 frameworks/base/core/java/android/content/ContextWrapper.java

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    return mBase.bindService(service, conn, flags);
}

这里mBase变量是ContextImpl类型,是在创建activity的时候,new 一个ContextImpl对象,赋值给activity的。

2 frameworks/base/core/java/android/app/ContextImpl.java

@Override
public boolean bindService(Intent service, ServiceConnection conn,
        int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}

       看bindServiceCommon里的mMainThread.getHandler,其中mMainTharead是ActivityThread的实例,可以先看下 mMainThread.getHandler的方法。

3 frameworks/base/core/java/android/app/ActivityThread.java

final H mH = new H();
final Handler getHandler() {
    return mH;
}

这个是ActivityThread的内部类H的实例,H类继承Hander。

接着看上面的bindServiceCommon方法。

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) {
            //位置1
            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);
        //位置2
        int res = ActivityManager.getService().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();
    }
}

先看位置1的mPackageInfo.getServiceDispatcher 。

4 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) {
            if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
            sd = map.get(c);
        }
        if (sd == null) {
            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 sd.getIServiceConnection();
    }
}

       在getServiceDispatcher函数中,传进来的参数context是一个调用bindService的activity实例,先以它为Key值在mServices中查看是否已经存在相应的ServiceDispatcher实例,如果有则不用创建直接取出。在该情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在ServiceDispatcher实例的内部,并创建一个InnerConnection对象,它是一个Binder对象,会传递给ActivityM

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值