首页 > 其他分享 >android App启动流程

android App启动流程

时间:2024-03-14 20:03:33浏览次数:22  
标签:... String int App options reason intent android 流程

App启动流程分为2个部分,一个是系统开机,拉起Launcher APP。另一个流程分为Launcher APP点击桌面应用图标,然后启动APP。我们首先分析Launcher APP的启动。

Launcher APP的启动:

android启动流程-SystemServer一篇文章中我们简单提过Launcher APP启动的过程,本章我们具体分析一下Launcher APP是怎么启动的。

还是先从ActivityManagerService.systemReady看起,往下执行。

ActivityManagerService

ActivityManagerService.systemReady->ActivityTaskManagerInternal.startHomeOnAllDisplays

/**
* Ready. Set. Go!
*/
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {

    ...    

    if (isBootingSystemUser && !UserManager.isHeadlessSystemUserMode()) {
        t.traceBegin("startHomeOnAllDisplays");
        mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
        t.traceEnd();
    }

    ...
}

ActivityTaskManagerService

ActivityTaskManagerInternal.startHomeOnAllDisplays->ActivityTaskManagerService.startHomeOnAllDisplays->RootWindowContainer.startHomeOnAllDisplaysex

​
final class LocalService extends ActivityTaskManagerInternal {

    ...

    @Override
    public boolean startHomeOnAllDisplays(int userId, String reason) {
        synchronized (mGlobalLock) {
            return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
        }
    }

    ...

}
​

RootWindowContainer

boolean startHomeOnAllDisplays(int userId, String reason) {
    boolean homeStarted = false;
    for (int i = getChildCount() - 1; i >= 0; i--) {
        final int displayId = getChildAt(i).mDisplayId;
        homeStarted |= startHomeOnDisplay(userId, reason, displayId);
    }
    return homeStarted;
}

boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
            false /* fromHomeKey */);
}

boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
                           boolean fromHomeKey) {
    // Fallback to top focused display or default display if the displayId is invalid.
    if (displayId == INVALID_DISPLAY) {
        final Task rootTask = getTopDisplayFocusedRootTask();
        displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;
    }

    final DisplayContent display = getDisplayContent(displayId);
    return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
                    result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                            allowInstrumenting, fromHomeKey),
            false /* initValue */);
}


boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,boolean allowInstrumenting, boolean fromHomeKey) {
    
    ...    

    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);
    return true;
}

ActivityStartController

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
                       TaskDisplayArea taskDisplayArea) {

    ...

    mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
            .setOutActivity(tmpOutRecord)
            .setCallingUid(0)
            .setActivityInfo(aInfo)
            .setActivityOptions(options.toBundle())
            .execute();
    mLastHomeActivityStartRecord = tmpOutRecord[0];
    if (rootHomeTask.mInResumeTopActivity) {
        // If we are in resume section already, home activity will be initialized, but not
        // resumed (to avoid recursive resume) and will stay that way until something pokes it
        // again. We need to schedule another resume.
        mSupervisor.scheduleResumeTopActivities();
    }
}

我们接着看:

 ActivityStarter obtainStarter(Intent intent, String reason) {
     return mFactory.obtain().setIntent(intent).setReason(reason);
 }

static class DefaultFactory implements Factory {
    @Override
    public ActivityStarter obtain() {
        ActivityStarter starter = mStarterPool.acquire();

        if (starter == null) {
            if (mService.mRootWindowContainer == null) {
                throw new IllegalStateException("Too early to start activity.");
            }
            starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
        }
  
        return starter;
    }
}

int execute() {
    ...

    try {
        res = executeRequest(mRequest);

    } finally {
        mRequest.logMessage.append(" result code=").append(res);
        Slog.i(TAG, mRequest.logMessage.toString());
        mRequest.logMessage.setLength(0);
    }
        
    ...

}

接着看executeRequest:

private int executeRequest(Request request) {

    ...
    
    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, checkedOptions,
            inTask, inTaskFragment, balCode, intentGrants, realCallingUid);

    if (request.outActivity != null) {
        request.outActivity[0] = mLastStartActivityRecord;
    }

    return mLastStartActivityResult;
}

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                                   IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                   int startFlags, ActivityOptions options, Task inTask,
                                   TaskFragment inTaskFragment, @BalCode int balCode,
                                   NeededUriGrants intentGrants, int realCallingUid) {

    ...

   
    try {
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
        result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, options, inTask, inTaskFragment, balCode,
                intentGrants, realCallingUid);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        startedActivityRootTask = handleStartResult(r, options, result, newTransition,
                remoteTransition);
    }
    
    ...

    return result;
}

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
                       IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                       int startFlags, ActivityOptions options, Task inTask,
                       TaskFragment inTaskFragment, @BalCode int balCode,
                       NeededUriGrants intentGrants, int realCallingUid) {

    ...

    mRootWindowContainer.resumeFocusedTasksTopActivities(
            mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
    
    ...

    return START_SUCCESS;
}

Launcher APP点击普通APP的启动:

ItemClickHandler:

Launcher APP点击普通APP时,会触发onClick方法:

private static void onClick(View v) {

    if (tag instanceof WorkspaceItemInfo) {
        onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
    } else if (tag instanceof FolderInfo) {
        if (v instanceof FolderIcon) {
            onClickFolderIcon(v);
        }
    } else if (tag instanceof AppInfo) {
        startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
    } else if (tag instanceof LauncherAppWidgetInfo) {
        if (v instanceof PendingAppWidgetHostView) {
            onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
        }
    } else if (tag instanceof ItemClickProxy) {
        ((ItemClickProxy) tag).onItemClicked(v);
    }
}

//最终会执行到这里
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
    
    ...
    
    launcher.startActivitySafely(v, intent, item);
}  

然后执行到ActivityContext中:

default RunnableList startActivitySafely(
        View v, Intent intent, @Nullable ItemInfo item) {

    ...

    if (isShortcut) {
        // Shortcuts need some special checks due to legacy reasons.
        startShortcutIntentSafely(intent, optsBundle, item);
    } else if (user == null || user.equals(Process.myUserHandle())) {
        // Could be launching some bookkeeping activity
        context.startActivity(intent, optsBundle);
    } else {
        context.getSystemService(LauncherApps.class).startMainActivity(
                intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
    }

    ...

}

Activity:

然后会执行到Activity.startActivity:

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    getAutofillClientController().onStartActivity(intent, mIntent);
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                   @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);

    }
    
    ...
}

然后执行Instrumentation.execStartActivity:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    
    ...
    
    int result = ActivityTaskManager.getService().startActivity(whoThread,
            who.getOpPackageName(), who.getAttributionTag(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()), token,
            target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
    
    ...
    
}

ActivityTaskManagerService

上面代码中ActivityTaskManager.getService()获取到ActivityTaskManagerService,所以我们接下来看ActivityTaskManagerService:

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
                               String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
                               String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
                               Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}


private int startActivityAsUser(IApplicationThread caller, String callingPackage,
                                @Nullable String callingFeatureId, Intent intent, String resolvedType,
                                IBinder resultTo, String resultWho, int requestCode, int startFlags,
                                ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    
    ...

    // TODO: Switch to user app stacks here.
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(opts)
            .setUserId(userId)
            .execute();

}

接下来的流程和Launcher APP启动流程一样了,最后附上整理了很久的流程图。供大家参考

流程图

标签:...,String,int,App,options,reason,intent,android,流程
From: https://blog.csdn.net/anhuilee/article/details/136686908

相关文章

  • 【面试题】手写call、apply、bind
    区别相同点:都可以改变函数的this指向第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window都可以利用后续参数传参不同点:call可以传入多个参数;apply需要传入一个参数对象(数组或类数组);bind可以分开传参,例如:constfoo=fn.bind(th......
  • Android各版本代号和对应API等级
    系统版本 代号 API等级Android13.0 T 33Android12.0 S 31,32Android11.0 R 30Android10.0 Q 29Android9.0 Pie 28Android8.1 Oreo 27Android8.0 Oreo 26Android7.1.1 Nougat 25Android7.0 Nougat ......
  • androidstudio不能选择java作为开发语言
    给我整笑了,。。。太久没用Androidstudio今天打开一堆错误,如:出现AppCompatActivity一直爆红问题,出现cannotresolvesymbolAppCompatActivity问题,出现Version28(intendedforAndroidPieandbelow)isthelastversionofthelegacysupportlibrary等问题,解决一个立马出现......
  • 2024年最新港区Apple ID注册教程
    大家都知道,许多海外应用在国内并不能直接下载,例如,TikTok在国内用不了,对跨境电商和海外社媒营销人员来说,如何有效地接触和利用各个国家或地区的在线资源,尤其是对于海外应用程序的接入是很重要的。不过许多做TikTok跨境电商的卖家会将Apple ID切换到港区,下载香港地区可用的TikT......
  • 注意!运用表单流程管理可一起实现提质增效
    经常会有客户在我们面前抱怨:到底用什么样的方法和软件,才能实现高效率的办公?其实,大家不必苦恼。因为低代码技术平台服务商流辰信息将会给大家推荐表单流程管理的实用性,它的灵活简便、易操作等优势特点,可以帮助大家实现高效率办公,创造更高市场价值。今天,我们一起来了解表单流程管理......
  • MATLAB神经网络——如何自定义属于自己的训练流程
    网络上大部分matlab神经网络训练流程都应用matlab内置的相关训练函数进行训练,如何让matlab神经网络训练过程拥有像pytorch一样的训练过程呢?本文将通过一个案例介绍如何利用matlab自定义自己的训练流程,希望对你有所启迪,让我们开始吧!clear,clc加载并处理原始数据  我们使用......
  • 太久没用Android studio出现AppCompatActivity爆红无法识别
    AndroidStudio中找不到AppCompatActivity一直报红,且xml中的布局控件也在报红处理方法_appcompatactivity找不到-CSDN博客 解决办法:打开file--projectstructure,点开dependecies,点击添加,输入com.android.support:appcompat-v7添加即可  然后就好了/ ......
  • 火山引擎VeDI:A/B实验如何应用在APP推荐系统中?
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 在移动互联网飞速发展的时代,用户规模和网络信息量呈现出爆炸式增长,信息过载加大了用户选择的难度,这样的背景下,推荐系统应运而生,为用户提供个性化的内容推荐。推荐系统在不断迭代中,其......
  • Android 桌面小组件使用
    原文:Android桌面小组件使用-Stars-One的杂货小窝借助公司上的几个项目,算是学习了Android桌面小组件的用法,记下踩坑记录基本步骤1.创建小组件布局这里需要注意的事,小组件布局里不能使用自定义View,只能使用原生的组件,比如说LinearLayout,TextView,连约束布局都不能使......
  • WanAndroid(鸿蒙版)开发的第二篇
    前言DevEcoStudio版本:4.0.0.600WanAndroid的API链接:玩Android开放API-玩Android-wanandroid.com1、WanAndroid(鸿蒙版)开发的第一篇2、WanAndroid(鸿蒙版)开发的第二篇3、WanAndroid(鸿蒙版)开发的第三篇4、WanAndroid(鸿蒙版)开发的第四篇5、WanAndroid(鸿蒙版)开......