android启动-application的启动流程(代码片段)

冬天的毛毛雨 冬天的毛毛雨     2023-01-15     801

关键词:

基于Android11-API30

总览

  1. 获取applicationThread,AMS这两个Binder
    2.attach时,将获取applicationThread对象也传递到AMS进程,请求远程调用通知AMS应用进程想要创建Application,此时AMS为服务端
  2. AMS收到消息,请求调用applicationThread的远程接口,此时AMS为客户端
  3. applicationThread收到AMS的请求,通过Handler发起创建Application的处理任务,后面就没有远程接口调用了
  4. 通过反射创建Application的实例,通过Instrumentation启动Application的onCreate方法

详细流程分析

从 ActivityThread.java 的main方法开始看;

public static void main(String[] args) 
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(system=false, startSeq);//1
    ...

进入attach方法;

if(!system)
    final IActivityManager mgr = ActivityManager.getService();
    try 
        mgr.attachApplication(mAppThread, startSeq);//1
     catch (RemoteException ex) 
        throw ex.rethrowFromSystemServer();
    

非系统应用流程,根据 getSeervice和捕获的RemoteException可以断定,此处在使用Binder进行远程接口调用。
转身看下mAppThread是什么?

final ApplicationThread mAppThread = new ApplicationThread();

private class ApplicationThread extends IApplicationThread.Stub 
    //批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
    public final void schedule*
    
    //TODO 关键方法
    public final void bindApplication(some args)//1
    
    //一堆dump方法,比如dumpMemory、dumpActivity等
    

可以看到,ApplicationThread是一个实现了远程接口的Binder客户端,内部封装实现了很多远程接口。不过这个客户端什么时候连接的服务器还未可知,没有找到bindService关键字,反正此时应该已经连接上对应的Service了。应该是在RuntimeInit.java类中进行应用进程启动时启动的。

回来看下前一步服务的实例IActivityManager.attachApplication()内部的实现。

  1. 先获取AMS的实例,此处获取AMS实例代码跟Activity启动流程中一致
public static IActivityManager getService() 
    return IActivityManagerSingleton.get();

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() 
            @Override
            protected IActivityManager create() 
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            
        ;

…获取到AMS的Binder后,继续查看ActivityManagerService.java中的attachApplication方法

public final void attachApplication(IApplicationThread thread, long startSeq) 
    
   	synchronized (this) 
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq); //1
        Binder.restoreCallingIdentity(origId);
    

单例获取AMS实例,AMS服务在系统启动就已经注册到ServiceManager了,此处直接去获取Binder实例就行,ServiceManager以Binder池的方式管理注册的Server。

AMS的attachApplication方法中进入到attachApplicationLocked方法,捡能看懂的代码看,跟着thread参数查看代码。

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
            int pid, int callingUid, long startSeq) 

    try 
        AppDeathRecipient adr = new AppDeathRecipient(
                app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);//1
        app.deathRecipient = adr;
     catch (RemoteException e) 
        app.resetPackageList(mProcessStats);
        mProcessList.startProcessLocked(app,
                new HostingRecord("link fail", processName),
                ZYGOTE_POLICY_FLAG_EMPTY);
        return false;
    

    final ActiveInstrumentation instr2 = app.getActiveInstrumentation();

    if (instr2 != null) //2
        thread.bindApplication(processName, appInfo, providerList,
                instr2.mClass,
                profilerInfo, instr2.mArguments,
                instr2.mWatcher,
                instr2.mUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.mDisabledCompatChanges);
     else 
        thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                null, null, null, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.isPersistent(),
                new Configuration(app.getWindowProcessController().getConfiguration()),
                app.compat, getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked(),
                buildSerial, autofillOptions, contentCaptureOptions,
                app.mDisabledCompatChanges);
    


先给ApplicationThread这个Binder上个死亡代理,根据这个死亡代理应该可以找到对应的Service是如何重新启动的,感兴趣可以继续深入,咱们继续往下走。
此处调用到thread.bindApplication接口,前面咱们查看ApplicationThread时有看到,直接切入。

private class ApplicationThread extends IApplicationThread.Stub 
    //批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
    public final void schedule*
    
    //TODO 关键方法
    public final void bindApplication(some args)
        AppBindData data = new AppBindData();
        ...一堆参数
        sendMessage(H.BIND_APPLICATION, data);//1
    
    
    //一堆dump方法,比如dumpMemory、dumpActivity等
    

到达咱们Android开发工程师比较熟悉的点了,封装了一堆参数后,通过H这个Handler对象发了一条BIND_APPLICATION消息,咱们看看这条消息去哪了,直接跟进BIND_APPLICATION这个消息的捕捉位置。

//消息分发
class H extends Handler
    public void handleMessage(Message msg)
        swich(msg.what)
            case BIND_APPLICATION: 
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);//1
                break;
            ...省略
        
    

进入消息分发处理方法,这个方法比较长,注意阅读能看懂的代码,不求甚解,跟踪data的处理。

private void handleBindApplication(AppBindData data) 
    //各种初始化,比如进程名,应用名,AsyncTask线程池的配置,时区,网络发现
    
    //Context的初始化
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    
    try 
        final ClassLoader cl = instrContext.getClassLoader();
        mInstrumentation = (Instrumentation)//1
            cl.loadClass(data.instrumentationName.getClassName()).newInstance();
     catch (Exception e) 
        throw new RuntimeException(
            "Unable to instantiate instrumentation "
            + data.instrumentationName + ": " + e.toString(), e);
    
    
    final ComponentName component = new ComponentName(ii.packageName, ii.name);
    mInstrumentation.init(this, instrContext, appContext, component,//1
            data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
            
    ...
    Application app;
    app = data.info.makeApplication(data.restrictedBackupMode, null);//2

    mInstrumentation.onCreate(data.instrumentationArgs);
    mInstrumentation.callApplicationOnCreate(app);//3

通过反射实例化mInstrumentation对象,该对象为Android系统组件的管家,目前看可以控制Application和Activity的生命周期。

创建Application对象,进去看下创建的代码

//LoadApk.java #makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
    Instrumentation instrumentation)
    ...
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);//1
    appContext.setOuterContext(app);
    ...


//Instrumentation.java #newApplication
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException 
    Application app = getFactory(context.getPackageName())
            .instantiateApplication(cl, className);//2
    app.attach(context);//首先回调attachBaseContext方法
    return app;


//AppComponentFactory #instantiateApplication
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
        @NonNull String className)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException 
    return (Application) cl.loadClass(className).newInstance();//3

可以看出最后还是通过反射初始化了Application。

最后通过mInstrumentation对象完成Application类的onCreate方法的调用。

mInstrumentation.callApplicationOnCreate(app);//1

//Instrumentation.java #callApplicationOnCreate
public void callApplicationOnCreate(Application app) 
    app.onCreate();

在启动activity之前,调用application的oncreate

 <application android:label="@string/app_name" android:icon="@drawable/icon" android:name="org.cocos2dx.lua.TestApplication">//加上application的路径//要调用的applicationpackageorg.cocos2d 查看详情

android12.0适配——应用启动动画

...做法是给Application或者第一个启动的Activity的主题添加上android:windowBackground属性来优化体验。到了Android12,官方新增了SplashScreenApi,可为所有应用添加新的启动动画,显示速度十分实时,所以到了Android12,我们就不必自己添加andro... 查看详情

android冷启动优化

1.什么是冷启动冷启动的定义:冷启动就是在启动应用前,系统中没有该应用的任何进程信息。冷启动和热启动的区别:热启动是用户使用返回键退出应用,然后马上又启动应用。热启动因为是从已有的进程中启... 查看详情

android逆向加壳的android应用启动流程|使用反射替换loadedapk中的类加载器流程(代码片段)

文章目录一、加壳的Android应用启动流程二、使用反射替换LoadedApk中的类加载器流程一、加壳的Android应用启动流程加壳的Android应用启动流程:加壳的Android应用执行时,壳代码获取应用的执行权限,然后将加壳的应用修正后,获得真正... 查看详情

android逆向加壳的android应用启动流程|使用反射替换loadedapk中的类加载器流程(代码片段)

文章目录一、加壳的Android应用启动流程二、使用反射替换LoadedApk中的类加载器流程一、加壳的Android应用启动流程加壳的Android应用启动流程:加壳的Android应用执行时,壳代码获取应用的执行权限,然后将加壳的应用修正后,获得真正... 查看详情

android性能优化---启动优化--1(启动优化介绍+启动时间测量)

启动优化介绍(1)背景介绍为什么要进行启动优化?第一体验和八秒定律,用户接触app首先就是第一体验比较重要,其次,app如果打开时间超过8s,大概会流失70%的用户。(2)启动分类:冷启动、热启动、温启动冷启动:特点:... 查看详情

android性能优化---启动优化--1(启动优化介绍+启动时间测量)

启动优化介绍(1)背景介绍为什么要进行启动优化?第一体验和八秒定律,用户接触app首先就是第一体验比较重要,其次,app如果打开时间超过8s,大概会流失70%的用户。(2)启动分类:冷启动、热启动、温启动冷启动:特点:... 查看详情

android冷启动优化

1.什么是冷启动冷启动的定义:冷启动就是在启动应用前,系统中没有该应用的任何进程信息。冷启动和热启动的区别:热启动是用户使用返回键退出应用,然后马上又启动应用。热启动因为是从已有的进程中启... 查看详情

Android中的动态启动活动?

】Android中的动态启动活动?【英文标题】:DynamicstartactivityinAndroid?【发布时间】:2011-06-1821:32:37【问题描述】:有没有办法根据条件动态更改Android中的启动活动?我试图做的(没用)如下:删除我的AndroidManifest.xml中定义的LAUNCH... 查看详情

android获取app启动时间

1.通过看logcat下的日志2.通过adb命令3.通过写代码获取3.1写一个工具类打印系统时间3.2在Application启动的时候打印开始时间3.3在MainActivity或者SplashActivity的相关函数中打印最后的时间 查看详情

android源码分析activity启动(代码片段)

Android 启动类的作用Instrumentation    完成对Application和Activity初始化和生命周期调用的工具类。用来监控系统与应用的交互。ActivityThread    管理应用进程的主线程的执行。ApplicationThread    用来实现ActivityManagerService与ActivityT... 查看详情

android7.0应用冷启动流程分析(代码片段)

最近在为自己MotoG定制Rom,顺便重新读了一遍Android7.0的相关源码,特此记录当做笔记.在开始正文之前,首先要明白冷启动和热启动.所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket... 查看详情

android项目优化:启动页面优化(代码片段)

一、启动页黑屏的问题1.1问题现象描述AndroidApp启动页面黑屏的问题,现象表现为:Android 开发App 启动时若没有做特殊处理的话,会出现一瞬间的白屏现象。即使启动页界面就加载一个布局,不做其他耗时处理,貌似也会... 查看详情

在android开发中怎样使用application类

1、Application和Activity,Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。2、Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Applic... 查看详情

外部化从 SCDF 启动的任务或作业的 application.properties

】外部化从SCDF启动的任务或作业的application.properties【英文标题】:Externalizeapplication.propertiesoftasksorJobslaunchedfromSCDF【发布时间】:2020-11-1616:36:24【问题描述】:我在openshift环境中运行SCDF。我使用SCDF在同一环境中启动批处理作业... 查看详情

application:didfinishlaunchingwithoptions:

iOS程序启动时总会调用application:didFinishLaunchingWithOptions:方法,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有此程序启动的原因。1、若用户直接启动,lauchOptions内无数据;2、若由其他应用程序通过openURL:启动,则UIA... 查看详情

android性能优化之加快应用启动速度

应用的启动启动方式通常来说,在安卓中应用的启动方式分为两种:冷启动和热启动。1、冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式... 查看详情

android面试题整理三

应用进程是怎么启动的?应用是怎么启用Binder()机制的?什么时候支持Binder机制的?进程启动后在ProcessState里做的谈谈你对Application的理解Application有什么作用?保存应用进程内的全局变量初始化操作提供应用... 查看详情