Android Studio ‘Run‘ 按钮后面的秘密(Grade学习【一】)

 

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

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

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

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

Android Studio 留下的面包屑

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

  • 点击Android Studio 右下角 ‘Event Log’

     

20:55   Executing tasks: [:app:assembleDebug]

20:55   Gradle build finished in 16s 500ms
  • 点击Android Studio 左下角的 ‘4:Run’

     

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 修改为 Release ,点击 RUN 按钮后执行的就是 assembleRelease.

 

下面我们把 Build Variants 修改为 Release,点击 ‘RUN’ 按钮,点击底部的

,可以看到执行的 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 官网的打包流程图,先学习一下。

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

APK 构建流程

APK 构建概览

来源:Build System Overview

APK 构建详细流程

来源:build-workflow

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

图中使用的工具在哪里?

<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。

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,唤起首屏等等。

可以在as下面的run面板上看到系统依次调用了如下的命令:

1. adb push 电脑上apk的绝对路径 /data/local/tmp/应用包名
复制apk到 /data/local/tmp目录下

2. adb shell pm install -r "/data/local/tmp/包名"
执行pm install 安装apk

3. adb shell am start -n "包名/.LauncherActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
启动应用的category为launcher对应的activity

参考资料

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值