温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android Service怎么实现

发布时间:2023-01-03 10:18:00 来源:亿速云 阅读:114 作者:iii 栏目:开发技术

今天小编给大家分享一下Android Service怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    一.APP侧启动Service

    其实启动service和启动Activity是很相似的,都是APP通知系统侧,由系统侧完成的整个流程。

    1.1 前台和后台启动

    无论是Activity,还是service,还是Application,都继承自Context的抽象类,所以可以使用Context的各种功能,就比如这了要介绍的启动前台/后台service。

    Context在安卓中,使用了一种典型的代理模式,我们调用的startService或者startForegroundService方法,最终都会委托给ContextImpl中的startService和startForegroundService来处理的。我们就来看下ContextImpl中的这两个方法:

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

    果然和我猜测的差不多,无论前台还是后台启动,其实最终都会走到一个方法中,只是配置参数的区别而已。最终都会走执行startServiceCommon方法。

    1.2startServiceCommon

    该方法中,通过binder通知系统的AMS完成对应的service的启动操作:

     ComponentName cn = ActivityManager.getService().startService(
                        mMainThread.getApplicationThread(), service,
                        service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                        getOpPackageName(), getAttributionTag(), user.getIdentifier());

    接下来,我们就看下系统侧是如何处理Service启动流程的。

    二.系统侧分发处理Service的启动逻辑

    系统侧的处理我主要分为3块来讲:

    1.系统接受APP侧的通知并转发

    2.系统侧委托ActiveServices负责完成的处理流程

    3.收到APP侧执行完成的回调,进行收尾操作

    2.1 AMS接受启动service的通知

    APP侧持有system_server进程的binder,上面讲到,它会通过binder方法startService完成对系统侧的通知。所以AMS的startService会收到这个通知。

    我们看下代码,发现AMS会把整个service的逻辑全部交由ActiveServices来处理,代码如下:

     try {
                    res = mServices.startServiceLocked(caller, service,
                            resolvedType, callingPid, callingUid,
                            requireForeground, callingPackage, callingFeatureId, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }

    系统代码startServiceLocked方法中,代码虽然很长,但是却遵循着一个不变的宗旨:位语句,即前面处理各种异常的分支逻辑,把核心流程留到方法的最终来处理。

    所以我们直接看startServiceLocked方法的最后一部分即可:

    final ComponentName realResult =
                    startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
                    allowBackgroundActivityStarts, backgroundActivityStartsToken);

    startServiceInnerLocked方法中,处理逻辑也是比较简单的,最终会交给bringUpServiceLocked方法来进行处理。而bringUpServiceLocked方法中则最终会交给realStartServiceLocked完成整个流程。好像系统代码都喜喜欢用realStart,Activity启动的流程中也有一个方法叫realStartActivity。

    2.2realStartServiceLocked流程

    realStartServiceLocked方法中,我们总结为三个流程:

    1.bumpServiceExecutingLocked,启动超时检查。

    2.thread.scheduleCreateService通知APP一侧去创建Service。

    3.sendServiceArgsLocked通知APP执行Service的生命流程。

    private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
                IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
                boolean enqueueOomAdj) throws RemoteException {
            //1.启动超时检查
            bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
            ...
            //2.通知APP创建service
                thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                        app.mState.getReportedProcState());
                r.postNotification();
                created = true;
            ...
            //3.通知执行service生命流程
            sendServiceArgsLocked(r, execInFg, true);
           ...
        }

    三.系统侧通知APP启动Service

    一般情况下,APP侧会收到系统侧发过来两种类型的通知,

    第一种:创建Service的任务通知

    第二种:执行Service生命流程的通知,通知Service执行onStartCommand方法。

    ApplicationThread接受通知并创建Service

    系统侧持有APP侧的binder,会通过scheduleCreateService这个binder方法通知APP一侧进行相应的操作。而APP侧,完成这个工作接收的就是ApplicationThread中的scheduleCreateService方法。该方法收到通知后,通过handler切换到主线程处理:

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

    handle中,会切换到主线程执行ActivityThread的handleCreateService方法。

    主要执行了如下的几段逻辑:

    1.如果是首次创建App进程的话,则需要重新创建Application;

    2.创建Service对象;

    3.调用service的attach方法进行关联;

    4.调用service的onCreate生命周期方法;

    5.创建完成后,通过serviceDoneExecuting通知系统侧创建完成。

    try {
                if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                final java.lang.ClassLoader cl;
                if (data.info.splitName != null) {
                    cl = packageInfo.getSplitClassLoader(data.info.splitName);
                } else {
                    cl = packageInfo.getClassLoader();
                }
                service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
                ContextImpl context = ContextImpl.getImpl(service
                        .createServiceBaseContext(this, packageInfo));
                if (data.info.splitName != null) {
                    context = (ContextImpl) context.createContextForSplit(data.info.splitName);
                }
                if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
                    final String attributionTag = data.info.attributionTags[0];
                    context = (ContextImpl) context.createAttributionContext(attributionTag);
                }
                // Service resources must be initialized with the same loaders as the application
                // context.
                context.getResources().addLoaders(
                        app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
                context.setOuterContext(service);
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                service.onCreate();
                mServicesData.put(data.token, data);
                mServices.put(data.token, service);
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }

    ApplicationThread接受通知并执行Service的生命流程

    同样的,这里完成接受的是,仍然是ApplicationThread中的方法。这个流程中的接受方法是scheduleServiceArgs方法。

    ApplicationThread中,收到通知后,通过handler把任务转交到主线程。

     public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
                List<ServiceStartArgs> list = args.getList();
                for (int i = 0; i < list.size(); i++) {
                    ServiceStartArgs ssa = list.get(i);
                    ServiceArgsData s = new ServiceArgsData();
                    s.token = token;
                    s.taskRemoved = ssa.taskRemoved;
                    s.startId = ssa.startId;
                    s.flags = ssa.flags;
                    s.args = ssa.args;
                    sendMessage(H.SERVICE_ARGS, s);
                }
            }

    接下来handler中切换到主线程会执行ActivityThread的handleServiceArgs方法。

    handleServiceArgs方法主要会完成以下几件事:

    1.找到对应的service,调用起onStartCommand方法;

    2.通知系统侧回调完成。

    private void handleServiceArgs(ServiceArgsData data) {
            CreateServiceData createData = mServicesData.get(data.token);
            Service s = mServices.get(data.token);
            if (s != null) {
                try {
                    if (data.args != null) {
                        data.args.setExtrasClassLoader(s.getClassLoader());
                        data.args.prepareToEnterProcess(isProtectedComponent(createData.info),
                                s.getAttributionSource());
                    }
                    int res;
                    if (!data.taskRemoved) {
                        res = s.onStartCommand(data.args, data.flags, data.startId);
                    } else {
                        s.onTaskRemoved(data.args);
                        res = Service.START_TASK_REMOVED_COMPLETE;
                    }
                    QueuedWork.waitToFinish();
                    try {
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to start service " + s
                                + " with " + data.args + ": " + e.toString(), e);
                    }
                }
            }
        }

    以上就是“Android Service怎么实现”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI