美文网首页Android开发
Android Studio 'Run' 按钮后

Android Studio 'Run' 按钮后

作者: ChuckChan | 来源:发表于2018-06-26 20:57 被阅读550次
    android_studio_btn_run.PNG

    'Run' 按钮,一点下,Android Studio 就会开动,代码奇迹般地变成 APK,被安装到手机上,显示 APP 的界面。背后发生了什么?

    点击 Run 按钮依次执行了 3 部分内容

    1. 检查项目和读取基本配置
    2. Gradle Build
    3. APK Install & Launch Activity

    让我们继续,看看这个结论是怎么来的,以及一路上还发现了什么。

    Android Studio 留下的面包屑

    Android Studio 给我们留下了什么——日志

    • 点击Android Studio 右下角 'Event Log'


      android_studio_tab_event_log.PNG
    20:55   Executing tasks: [:app:assembleDebug]
    
    20:55   Gradle build finished in 16s 500ms
    
    • 点击Android Studio 左下角的 '4:Run' android_studio_tab_run.PNG
    06/25 20:55:44: Launching app
    $ adb push F:\workspace\AndroidBuildProcess\app\build\outputs\apk\debug\app-debug.apk /data/local/tmp/com.example.buildprocess.androidbuildprocess
    $ adb shell pm install -t -r "/data/local/tmp/com.example.buildprocess.androidbuildprocess"
        pkg: /data/local/tmp/com.example.buildprocess.androidbuildprocess
    Success
    
    
    $ adb shell am start -n "com.example.buildprocess.androidbuildprocess/com.example.buildprocess.androidbuildprocess.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
    

    根据日志,可见:

    1. 执行了 Gradle task:assembleDebug
    2. 安装 apk, 启动 MainActivity

    assembleDebug/assembleRelease

    执行的是 assembleRelease 还是 assembleDebug 实际是由 build variants 设置的类型决定的。

    build_variants.PNG

    如果 Build Variants 修改为 Release ,点击 RUN 按钮后执行的就是 assembleRelease.

    下面我们把 Build Variants 修改为 Release,点击 'RUN' 按钮,点击底部的 android_studio_tab_build.PNG

    ,可以看到执行的 tasks 如下:

    completed successfully  51s 886ms
    Starting Gradle Daemon  2s 23ms
    Run build   42s 250ms
    Load build  1s 89ms
    Configure build 6s 598ms
    Calculate task graph    129ms
    Run tasks   33s 806ms
    Finalize build cache configuration  1ms
    :app:preBuild   15ms
    :app:preReleaseBuild    783ms
    :app:compileReleaseAidl 173ms
    :app:compileReleaseRenderscript 112ms
    :app:checkReleaseManifest   12ms
    :app:generateReleaseBuildConfig 45ms
    :app:prepareLintJar 5ms
    :app:mainApkListPersistenceRelease  34ms
    :app:generateReleaseResValues   8ms
    :app:generateReleaseResources   1ms
    :app:mergeReleaseResources  7s 961ms
    :app:createReleaseCompatibleScreenManifests 73ms
    :app:processReleaseManifest 392ms
    :app:splitsDiscoveryTaskRelease 32ms
    :app:processReleaseResources    2s 134ms
    :app:generateReleaseSources 1ms
    :app:javaPreCompileRelease  865ms
    :app:compileReleaseJavaWithJavac    2s 264ms
    :app:compileReleaseNdk  
    :app:compileReleaseSources  
    :app:lintVitalRelease   4s 93ms
    :app:mergeReleaseShaders    18ms
    :app:compileReleaseShaders  11ms
    :app:generateReleaseAssets  
    :app:mergeReleaseAssets 56ms
    :app:transformClassesWithDexBuilderForRelease   2s 292ms
    :app:transformDexArchiveWithExternalLibsDexMergerForRelease 6s 124ms
    :app:transformDexArchiveWithDexMergerForRelease 1s 461ms
    :app:mergeReleaseJniLibFolders  94ms
    :app:transformNativeLibsWithMergeJniLibsForRelease  1s 749ms
    :app:processReleaseJavaRes  
    :app:transformResourcesWithMergeJavaResForRelease   1s 653ms
    :app:validateSigningRelease 4ms
    :app:packageRelease 1s 133ms
    :app:assembleRelease    1ms
    

    为了更加详细的分析 assembleRelease 执行的内容,执行以下命令:

    linux/macOS

    ./gradlew assembleRelease --info > output.txt
    

    windows

    gradlew.bat assembleRelease --info > output.txt
    

    可以从 output.txt 文件看到详细的处理过程。

    来自官方的说明

    Android Stuido 打包流程

    来源:Configure your build

    以下是 Android 官网的打包流程图,先学习一下。


    build-process_2x.png
    1. 编译器将应用工程下的源码、资源文件、 AIDL 文件,依赖的 Module 、 AAR 库、 JAR 包转换成 DEX 文件, 其他的转换成已编译资源。
    2. 将 DEX 文件和已编译资源合并成单个 APK 。
    3. 使用 debug 或者 release keystore 对 APK 进行签名。
    4. 在生成最终的 APK 之前,打包器会使用 zipalign 工具对 APK 进行优化,以便减少在设备上运行时使用的内存。

    APK 构建流程

    APK 构建概览

    来源:Build System Overview

    build.png

    APK 构建详细流程

    来源:build-workflow

    Android Build Process.png

    根据上图来说明一下构建的流程

    图中使用的工具在哪里?

    <SDK>/build-tools/<buildToolsVersion>/ 目录下

    1. aapt(Android Asset Packaging Tool) 打包资源文件,生成 R.java 和已编译资源(二进制文件)

      1. Merge
      * Merge Resources 
      * Merge Manifest
      * Merge Assets 
      
      1. aapt 工具将 Merged Resources 、Merged Manifest 、Merged Assets 处理生成 R.java 和 已编译资源
    2. aidl(Android Interface Definition Language ) 文件处理

      aidl 工具根据 aidl 文件生成 Java Classes

    3. Java源码编译

      Javac 编译 R.java 、Java 代码 、Java Classes 生成 .class 文件

    4. 代码混淆( proguard )

      使用 ProGuard 工具进行混淆

    5. 转化为 dex 文件

      dx 工具会将 .class 文件转化为 Dalvik 专用的 dex 文件

    6. APK Builder

      使用 sdklib.jar 的 ApkBuilder 类将 dex 文件、已编译资源打包生成 APK 文件。

    7. 对 APK 进行签名

      使用 apksigner.jar 对 APK 进行签名

    8. Zipalign 进行优化

      使用 zipalign 工具对 APK 进行内存对齐

    Android Studio 如何执行三个步骤

    来源:Run Configurations

    Android Run Configuration Execution Flow

    The previous section talked about the overall execution flow. In this section, we look at the specific parts implemented within the android plugin. Overall, there are 3 parts to this:

    1. User presses Run/Debug. At this point, AndroidRunConfigurationBase.getState is called, and it constructs and returns an AndroidRunState
    2. The Gradle build is performed.
    3. Once the build is complete, the actual deployment is performed by the AndroidRunState.execute method.

    以上是 Android Studio 对 IDEA 扩展中代码中对 Run Configuration 流程的说明。

    AS 对 IDEA 扩展的代码放在:JetBrains/android。打包进 AS 之后,代码位于:ANDROID_STUDIO/plugins/android/lib/android.jar

    使用以下工具查看 android.jar :

    • jd-gui
    • Luyten :如果 jd-gui 显示 '// INTERNAL ERROR //' ,不能显示类的内容,使用此工具

    检查项目和读取基本配置

    源代码位置:android/android/src/com/android/tools/idea/run/AndroidRunConfigurationBase.java

    public RunProfileState getState(@NotNull Executor executor, 
                                    @NotNull ExecutionEnvironment env)
        throws ExecutionException
      {
        // 验证项目( Gradle Sync 情况,是否是 Android 项目等)
        validateBeforeRun(executor);
        ...
          // 弹窗选择要安装的设备
          deviceFutures = deployTarget.getDevices(deployTargetState, facet, getDeviceCount(isDebugging), isDebugging, getUniqueID());
        ...
        // InstantRun 配置
        if ((supportsInstantRun()) && (instantRunEnabled) && (existingSessionInfo != null))
        {
            ...
        }
        ...
        return new AndroidRunState(env, getName(), module, applicationIdProvider, getConsoleProvider(), deviceFutures, providerFactory, processHandler);
      }
    

    可见:主要完成了对项目的检查,Instant Run 相关配置,选择安装设备等过程。

    Gradle Build

    在 RunState 创建完成之后,IDEA 允许你在执行之前,执行一些任务,比如一个 Java 项目在运行之前,你得编译。我们的 Android 项目也是类似,在安装和部署之前,你得编译打包。这个过程称之为:Before Launch。

    gradle_aware_make.PNG

    Android Studio 默认为我们提供 Gradle-aware Make 。

    如下面代码,本质上去执行了 Gradle Tasks,在 Debug 环境下默认是assembleDebug , 如果用户更改了 Build Variants 也会相应变化。

    源代码位置:android/android/src/com/android/tools/idea/gradle/run/MakeBeforeRunTaskProvider.java

    private static BeforeRunBuilder createBuilder(@NotNull final ExecutionEnvironment env, 
                                                  @NotNull final Module[] modules, 
                                                  @NotNull final RunConfiguration configuration, 
                                                  @Nullable final AndroidRunConfigContext runConfigContext, 
                                                  @Nullable final String userGoal) {
        ...
            // 组装 Gradle task:gradle[:"assemble" + compileType]
            if (deviceFutures == null || irContext == null) {
                return new DefaultGradleBuilder(gradleTasksProvider.getTasksFor(BuildMode.ASSEMBLE, testCompileType), BuildMode.ASSEMBLE);
            }
        ...
            return new InstantRunBuilder(getLaunchedDevice(targetDevices.get(0)), irContext, runConfigContext, gradleTasksProvider);
    }
    

    源代码位置:android/android/src/com/android/tools/idea/gradle/project/build/invoker/GradleBuildInvoker.java

    public void executeTasks(@NotNull final Request request) {
        ...
        // 真正执行 Gradle 命令
        final GradleTasksExecutor executor = this.myTaskExecutorFactory.create(request, this.myBuildStopper);
        final GradleTasksExecutor gradleTasksExecutor;
        final Runnable executeTasksTask = () -> {
            this.myDocumentManager.saveAllDocuments();
            gradleTasksExecutor.queue();
            return;
        };
        ...
    }
    

    APK Install & Launch Activity

    源代码位置:android/android/src/com/android/tools/idea/run/AndroidRunState.java

    在构建完成之后,会回到 RunState 的执行阶段,这一阶段应该叫做部署 : InstantRun 相关逻辑,版本判断,设备判断,输出日志,调用 pm 命令安装 APK,唤起首屏等等。

    参考资料

    相关文章

      网友评论

        本文标题:Android Studio 'Run' 按钮后

        本文链接:https://www.haomeiwen.com/subject/qgzmyftx.html