当前位置:   article > 正文

Android中的Service是如何启动的_一个apk,直接启动service启动不了,只有先打开activity,才能启动service

一个apk,直接启动service启动不了,只有先打开activity,才能启动service

1:前言

ServiceAndroid中的四大组件之一,日常开发中我们经常会使用startService之类的方法来启动Service,那这个方法调用的底层原理是什么呢?Android系统是如何启动起来Service的呢?本文我们从源码出发,介绍一下Android中的Service是如何启动Service的,本文的结构如下:

image-20210725130153407

2:源码分析

2.1:ContextImpl.startService&startForegroundService应用层调用的入口

我们调用startService/startForegroundService之后,会调用到android.app.ContextImpl#startService/startForegroundService

class ContextImpl extends Context {
     
    @Override
    public ComponentName startService(Intent service) {
   
        return startServiceCommon(service, false, mUser);
    }

    @Override
    public ComponentName startForegroundService(Intent service) {
   
        return startServiceCommon(service, true, mUser);
    }
  	
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
   
         ...
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

可以看到,startServicestartForegroundService最终调用的都是startServiceCommon这个方法,唯一不同的是第二个参数requireForeground的值不一样,用来标识当前Service是否是前台Serivice,我们来看startServiceCommon的具体实现:

class ContextImpl extends Context {
     
   private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
   
        try {
   
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                    getOpPackageName(), getAttributionTag(), 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());
                } else if (cn.getPackageName().equals("?")) {
   
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
   
            throw e.rethrowFromSystemServer();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

可以看到,核心是调用到了ActivityManager.getService().startService()方法进行Service的启动,即AMS中,我们来看一下AMS中是如何启动Service的.

2.2:ActivityManagerService.startService:执行前置判断,满足启动service的条件的话触发真正startService的逻辑

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub{
   
  	final ActiveServices mServices;
  
	 @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage,
            String callingFeatureId, int userId)
            throws TransactionTooLargeException {
   
        ...
        synchronized(this) {
   
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
   
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, callingFeatureId, userId);
            } finally {
   
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

可以看到,最终调用到了ActiveServices.startServiceLocked()中:

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
   
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            @Nullable String callingFeatureId, final int userId)
            throws TransactionTooLargeException {
   
        return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
                callingPackage, callingFeatureId, userId, false);
    }
  	
  	ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage,
            @Nullable String callingFeatureId, final int userId,
            boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
   
      	/**
      	*对当前Service的启动进行判断,看下Service启动的限制(比如权限、前后台等是否满足)
      	**/
      	...
        //启动Service
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);

        if (!r.mAllowWhileInUsePermissionInFgs) {
   
            r.mAllowWhileInUsePermissionInFgs =
                    shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid,
                            callingUid, service, r, allowBackgroundActivityStarts);
        }

        return cmp;
    }
  
   ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
   
       	...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        ...
        return r.name;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

核心是调用到了ActiveServices.bringUpServiceLocked.

2.3:ActiveServices.bringUpServiceLocked:根据进程&线程是否存在执行不同操作

//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
   
	   private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
   
     		//如果进程和线程已经不为空,说明该Service已经create了,直接调用sendServiceArgsLocked
        if (r.app != null && r.app.thread != null) {
   
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }

        ...
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        HostingRecord hostingRecord = new HostingRecord("service", r
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/273078
推荐阅读
相关标签
  

闽ICP备14008679号