四大组件之Service

来源:互联网 发布:cad平面设计软件 编辑:程序博客网 时间:2024/05/17 01:08

四大组件第二重要的就是Service了,有两种方式来启动,startService和BindService,看了一下和Activity似乎是一致的流程,只是Activity是有关联个Window来显示界面,Service没有。

方式1 StartService()

在Activity中找到这个方法,发现实际上只调用ContextWrapper里的函数代码如下

 @Override    public ComponentName startService(Intent service) {        return mBase.startService(service);    }

使用的是mBase这个Context来start的,看一下这个变量是哪里来的,追溯的Activity初始化的时候。

performLaunchActivity的时候会创建Activity,之后会调用attch来建立Activity必要联系,再attch中有这样的调用

attachBaseContext(context);
这里的context就是mBase,回到performLaunchActivity,
Context appContext = createBaseContextForActivity(r, activity);

创建的appContext这个Context,最后其实使用的是ContextImpl这个类。

static ContextImpl createActivityContext(ActivityThread mainThread,            LoadedApk packageInfo, IBinder activityToken, int displayId,            Configuration overrideConfiguration) {        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");        return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,                null, overrideConfiguration, displayId);    }

在这个类中,可以看到startService的代码

 @Override    public ComponentName startService(Intent service) {        warnIfCallingFromSystemProcess();        return startServiceCommon(service, mUser);    }


之后的StartServiceCommon代码如下,
private ComponentName startServiceCommon(Intent service, UserHandle user) {        try {            validateServiceIntent(service);            service.prepareToLeaveProcess(this);            ComponentName cn = ActivityManagerNative.getDefault().startService(                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(                            getContentResolver()), getOpPackageName(), user.getIdentifier());            if (cn != null) {                if (cn.getPackageName().equals("!")) {                    throw new SecurityException(                            "Not allowed to start service " + service                            + " without permission " + cn.getClassName());                } else if (cn.getPackageName().equals("!!")) {                    throw new SecurityException(                            "Unable to start service " + service                            + ": " + cn.getClassName());                }            }            return cn;        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }


代码中, ActivityManagerNative.getDefault()其实就是获得了ActivityManagerService,去观察一下那里是怎么启动的。

ActivityManagerService.java

 @Override    public ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, String callingPackage, int userId)            throws TransactionTooLargeException {        enforceNotIsolatedCaller("startService");        // 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");        }        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,                "startService: " + service + " type=" + resolvedType);        synchronized(this) {            final int callingPid = Binder.getCallingPid();            final int callingUid = Binder.getCallingUid();            final long origId = Binder.clearCallingIdentity();            ComponentName res = mServices.startServiceLocked(caller, service,                    resolvedType, callingPid, callingUid, callingPackage, userId);            Binder.restoreCallingIdentity(origId);            return res;        }    }

ActiveServices.java

startServiceLocked()//这里可能有一些查询的工作,看到取出一个map中services,有可能是使用action方式启动需要查询,没有仔细看。

startServiceInnerLocked()

bringUpServiceLocked()

 realStartServiceLocked(r, app, execInFg)

app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);

调用了AppThread(是ActivityThread的内部类)的ScheduleCreateService

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);        }

将Service的信息通过messge发送的H(主线程Handler),看一下处理

 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;

在handleCreatService中才真正实例化,建立必要联系,进入Service的生命周期代码如下

 private void handleCreateService(CreateServiceData data) {        // If we are getting ready to gc after going to the background, well        // we are back active so skip it.        unscheduleGcIdler();        LoadedApk packageInfo = getPackageInfoNoCheck(                data.info.applicationInfo, data.compatInfo);        Service service = null;        try {            java.lang.ClassLoader cl = packageInfo.getClassLoader();            service = (Service) cl.loadClass(data.info.name).newInstance();        } catch (Exception e) {            if (!mInstrumentation.onException(service, e)) {                throw new RuntimeException(                    "Unable to instantiate service " + data.info.name                    + ": " + e.toString(), e);            }        }        try {            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);            context.setOuterContext(service);            Application app = packageInfo.makeApplication(false, mInstrumentation);            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            service.onCreate();            mServices.put(data.token, service);            try {                ActivityManagerNative.getDefault().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);            }        }    }

看到使用java 的newInstance这种方式实例化Service如下

java.lang.ClassLoader cl = packageInfo.getClassLoader();            service = (Service) cl.loadClass(data.info.name).newInstance();

比且调用了 onCreate()回调,整个流程的activity很相似。


方式2 bindService()启动

一开始也是使用mBase.bindService(service, conn, flags)这中方式,同上面一致,经过ActiviyMangerService到ActiveServices,流程就差不多了。

这种方式下主要想分析一下是怎么调用Service的onBind()返回一个Binder的。

ContextImp.java

bindServiceCommon()这个方法中,

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

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) {                sd = map.get(c);            }            if (sd == null) {                sd = new ServiceDispatcher(c, context, handler, flags);                if (map == null) {                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();                    mServices.put(context, map);                }                map.put(c, sd);            } else {                sd.validate(context, handler);            }            return sd.getIServiceConnection();        }    }

在这个方法中返回一个接口,这个接口是aidl接口,查看了一下和正常的aidl生成的文件一致,有Bind ,还有binder的内部类Proxy,还有转发回调onTransact。

mService:一个应用中所有的,ServiceConnection对象,和ServiceDispatcher对象的对应关系map。

ServiceDispatcher:建立起ServiceConnection和InnerConnection的关系,InnerConnection代码如下

将这一对的ServiceConnection和ServiceDispatcher装到map中。

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) throws RemoteException {                LoadedApk.ServiceDispatcher sd = mDispatcher.get();                if (sd != null) {                    sd.connected(name, service);                }            }        }

简单来说,它调用了connect的时候调用了ServiceConnect的onServiceConnected方法。


关于存取对应关系的代码好复杂,不去看了,各种Map....看一下最后怎么调用的吧,

ActivityThread.java

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) {                        IBinder binder = s.onBind(data.intent);                        ActivityManagerNative.getDefault().publishService(                                data.token, data.intent, binder);                    } else {                        s.onRebind(data.intent);                        ActivityManagerNative.getDefault().serviceDoneExecuting(                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);                    }                    ensureJitEnabled();                } catch (RemoteException ex) {                    throw ex.rethrowFromSystemServer();                }            } catch (Exception e) {                if (!mInstrumentation.onException(s, e)) {                    throw new RuntimeException(                            "Unable to bind to service " + s                            + " with " + data.intent + ": " + e.toString(), e);                }            }        }    }

onBind()返回Binder,之后使用ActivityManagerService的PublisService(),又调用了publishServiceLocked。


 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {        final long origId = Binder.clearCallingIdentity();        try {            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r                    + " " + intent + ": " + service);            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++) {                            ConnectionRecord c = clist.get(i);                            if (!filter.equals(c.binding.intent.intent)) {                                if (DEBUG_SERVICE) Slog.v(                                        TAG_SERVICE, "Not publishing to: " + c);                                if (DEBUG_SERVICE) Slog.v(                                        TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);                                if (DEBUG_SERVICE) Slog.v(                                        TAG_SERVICE, "Published intent: " + intent);                                continue;                            }                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);                            try {                                c.conn.connected(r.name, service);                            } catch (Exception e) {                                Slog.w(TAG, "Failure sending service " + r.name +                                      " to connection " + c.conn.asBinder() +                                      " (in " + c.binding.client.processName + ")", e);                            }                        }                    }                }                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);            }        } finally {            Binder.restoreCallingIdentity(origId);        }    }



ConnectionRecord c = clist.get(i);

这句简单理解为从列表中取了出来,

c.conn.connected(r.name, service);

调用了这个方法onServiceConnected()。

以后工作深入在研究吧,现在也用不到。

原创粉丝点击