日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android构建流程——篇八

發布時間:2024/9/30 Android 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android构建流程——篇八 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • Task29 checkDebugLibraries
      • 1. inut/ouput
      • 2. 核心類(CheckMultiApkLibrariesTask)
    • Task30 processDebugJavaRes
      • 1. 預操作
      • 1. input/ouput
      • 核心類(ProcessJavaResConfigAction, SYNC)
    • Task31 transformResourcesWithMergeJavaResForDebug
      • 1. input/ouput
      • 2. 核心類(MergeJavaResourcesTransform)
    • Task32 validateSigningDebug
      • 核心類(ValidateSigningTask)
    • Task 33 packageDebug
      • 1. input/ouput
      • 2. 核心類(PackageApplication)

Task29 checkDebugLibraries

1. inut/ouput

taskName:checkDebugLibraries ========================================================= output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/check-libraries/debug

這個任務就是用來做校驗的,如果存在多個modules打包成相同庫,則會提示報錯

2. 核心類(CheckMultiApkLibrariesTask)

@TaskAction fun taskAction() {// Build a map of libraries to their corresponding modules. If two modules package the same// library, we will use the map to output a user-friendly error message.val map = mutableMapOf<String, MutableList<String>>()var found = falsefor (artifact in featureTransitiveDeps) {// Sanity check. This should never happen.if (artifact.id.componentIdentifier !is ProjectComponentIdentifier) {throw GradleException(artifact.id.componentIdentifier.displayName + " is not a Gradle project.")}val projectPath =(artifact.id.componentIdentifier as ProjectComponentIdentifier).projectPathif (artifact.file.isFile) {found = found || updateLibraryMap(artifact.file, projectPath, map)}}if (found) {// Build the error message. Sort map and projectPaths for consistency.val output = StringBuilder()for ((library, projectPaths) in map.toSortedMap()) {if (projectPaths.size > 1) {output.append(projectPaths.sorted().joinToString(prefix = "[", postfix = "]")).append(" all package the same library [$library].\n")}}throw GradleException(output.toString())}}private fun updateLibraryMap(file: File,projectPath: String,map: MutableMap<String, MutableList<String>> ): Boolean {var found = falsefor (library in Files.readLines(file, Charsets.UTF_8)) {val libraryWithoutVariant = library.substringBeforeLast("::")if (map.containsKey(libraryWithoutVariant)) {found = truemap[libraryWithoutVariant]?.add(projectPath)} else {map[libraryWithoutVariant] = mutableListOf(projectPath)}}return found }

Task30 processDebugJavaRes

1. 預操作

在debug/main目錄新增resources添加文件

1. input/ouput

taskName:processDebugJavaRes input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/src/main/resources/main-resources.txt input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/src/debug/resources/debug-resources.txt ========================================================= output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/sourceFolderJavaResources/debug

可以看到該任務就是將app中的resources中文件copy而已

核心類(ProcessJavaResConfigAction, SYNC)

// ProcessJavaResConfigAction.java public void execute(@NonNull Sync processResources) {// 執行預操作for (SourceProvider sourceProvider :scope.getVariantConfiguration().getSortedSourceProviders()) {processResources.from(((AndroidSourceSet) sourceProvider).getResources().getSourceFiles());}processResources.setDestinationDir(destinationDir);}

復制操作其實是交給SYNC這個類處理的,也就是sync任務,可以理解為是一個copy操作,只是可以通過preserve來指定目標目錄那些可以刪除,那些可以保留
具體參考官方文檔https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Sync.html

Task31 transformResourcesWithMergeJavaResForDebug

1. input/ouput

taskName:transformResourcesWithMergeJavaResForDebug input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/libs/java-json.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/adapters-3.2.0.aar/bc960c7c2fdbe5a1b97481ebd16e7d07/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/library-3.2.0.aar/de8b548685f788612cb022c06f944e21/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/modules-2/files-2.1/com.android.databinding/baseLibrary/3.2.0/fb5f8492c36231104cd86feaefa723291504c0a6/baseLibrary-3.2.0.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/multidex-1.0.2.aar/bf674b553893d1ca7ec3045705c93ed8/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/3835acebdd7fa231db259f7088788607/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/dafb9764e639c30db91be97006e47787/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-v4-26.1.0.aar/e50a7ebe45a7183db73f76387f58eadf/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-fragment-26.1.0.aar/68eceb6dacbf0dc308d62e2a91559369/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-core-utils-26.1.0.aar/137dca77f851b0e904bb098c1da042aa/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/animated-vector-drawable-26.1.0.aar/c49cb8624209768bd4984b8fead22f48/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-vector-drawable-26.1.0.aar/4a854f4c19aeb19de51777bbccdc7f48/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/6c38555fbd7f9d3e1a9de701d85ad85e/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-core-ui-26.1.0.aar/445504c8690be77ae0900482a270f4e9/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/160cc69dee260ec7a028fa1574fd87ba/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/transforms-1/files-1.1/runtime-1.0.3.aar/b7c442e59ee627256a254a2a31de63ac/jars/classes.jar input:/Users/dingbaosheng/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.0.3/7d7f60c4783872861222166f6164215f8951c7b1/common-1.0.3.jar input:/Users/dingbaosheng/.gradle/caches/modules-2/files-2.1/android.arch.core/common/1.0.0/a2d487452376193fc8c103dd2b9bd5f2b1b44563/common-1.0.0.jar input:/Users/dingbaosheng/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/26.1.0/814258103cf26a15fcc26ecce35f5b7d24b73f8/support-annotations-26.1.0.jar input:/Users/dingbaosheng/.gradle/caches/modules-2/files-2.1/com.android.support.constraint/constraint-layout-solver/1.1.3/bde0667d7414c16ed62d3cfe993cff7f9d732373/constraint-layout-solver-1.1.3.jar input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/sourceFolderJavaResources/debug/debug-resources.txt input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/sourceFolderJavaResources/debug/main-resources.txt ========================================================= output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/debug-mergeJavaRes/zip-cache output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/transforms/mergeJavaRes/debug

這個任務就是合并java資源文件(注意:此處資源文件不是指layout,asset,dex等資源文件)而是指標準等Java資源

看下mergeJavaRes/debug/0.jar產物,解壓如下

可以看到文件如下

  • META-INF記錄了App中注解處理器涉及的各庫版本
  • 我們在resources目錄添加的資源文件
  • 如果jar中包含.java文件也會被包含打包

2. 核心類(MergeJavaResourcesTransform)

核心類和task28一樣,此處略過

Task32 validateSigningDebug

該任務就是用來驗證deubug模式下keystore文件是否存在,如果不存在直接創建并保存,
因為我們Sample工程并沒有配置sign屬性,所以打包默認會使用debug-keystore進行簽名

核心類(ValidateSigningTask)

/*** A Gradle Task to check that the keystore file is present for this variant's signing config.** If the keystore is the default debug keystore, it will be created if it is missing.** This task has no explicit inputs, but is forced to run if the signing config keystore file is* not present.*/ open class ValidateSigningTask : AndroidVariantTask() {/*** Output directory to allow this task to be up-to-date, despite the the signing config file* not being modelled directly as an input or an output.*/@get:OutputDirectory lateinit var dummyOutputDirectory: Fileprivate setprivate lateinit var signingConfig: SigningConfigprivate lateinit var defaultDebugKeystoreLocation: File@TaskAction@Throws(ExecutionException::class, IOException::class)fun validate() = when {signingConfig.storeFile == null -> throw InvalidUserDataException("""Keystore file not set for signing config ${signingConfig.name}""")isSigningConfigUsingTheDefaultDebugKeystore() ->/* Check if the debug keystore is being used rather than directly checking if italready exists. A "fast path" of returning true if the store file is present wouldallow one task to return while another validate task has only partially written thedefault debug keystore file, which could lead to confusing transient build errors. */createDefaultDebugKeystoreIfNeeded()signingConfig.storeFile?.isFile == true -> {/* Keystore file is present, allow the build to continue. */}else -> throw InvalidUserDataException("""Keystore file '${signingConfig.storeFile?.absolutePath}' """+ """not found for signing config '${signingConfig.name}'.""")}// 如果/Users/{USER_NAME}/.android/debug.keystore不存在,創建一個debug.keystore@Throws(ExecutionException::class, IOException::class)private fun createDefaultDebugKeystoreIfNeeded() {checkState(signingConfig.isSigningReady, "Debug signing config not ready.")if (!defaultDebugKeystoreLocation.parentFile.canWrite()) {throw IOException("""Unable to create debug keystore in """+ """${defaultDebugKeystoreLocation.parentFile.absolutePath} because it is not writable.""")}/* Synchronized file with multi process locking requires that the parent directory of thedefault debug keystore is present.It is created as part of KeystoreHelper.defaultDebugKeystoreLocation() */checkState(FileUtils.parentDirExists(defaultDebugKeystoreLocation),"Parent directory of the default debug keystore '%s' does not exist",defaultDebugKeystoreLocation)/* Creating the debug keystore is done with the multi process file locking,to avoid one validate signing task from exiting early while the keystore is in theprocess of being written.The keystore is not locked in the task input presence check or where it is used atapplication packaging.This is generally safe as the keystore is only automatically created,never automatically deleted. */SynchronizedFile.getInstanceWithMultiProcessLocking(defaultDebugKeystoreLocation).createIfAbsent { createDefaultDebugStore(it, this.logger) }}private fun isSigningConfigUsingTheDefaultDebugKeystore(): Boolean {return signingConfig.name == BuilderConstants.DEBUG &&signingConfig.keyAlias == DefaultSigningConfig.DEFAULT_ALIAS &&signingConfig.keyPassword == DefaultSigningConfig.DEFAULT_PASSWORD &&signingConfig.storePassword == DefaultSigningConfig.DEFAULT_PASSWORD &&signingConfig.storeType == KeyStore.getDefaultType() &&signingConfig.storeFile.isSameFile(defaultDebugKeystoreLocation)}... }

Task 33 packageDebug

1. input/ouput

taskName:packageDebug input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/apk_list/debug/mainApkListPersistenceDebug/apk-list.gson input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/merged_assets/debug/mergeDebugAssets/out input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/transforms/dexMerger/debug/0 input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/transforms/mergeJavaRes/debug/0.jar input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/merged_manifests/debug/processDebugManifest/merged input:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/processed_res/debug/processDebugResources/out input:/Users/dingbaosheng/.android/debug.keystore ========================================================= output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/packageDebug/tmp output:/Users/dingbaosheng/work/mockuai/project/AndroidGradleTaskDemo/app/build/outputs/apk/debug

這個任務就是打包任務,把之前的任務產物作為輸入打包成一個apk,主要流程圖如下

2. 核心類(PackageApplication)

/** Task to package an Android application (APK). */ public class PackageApplication extends PackageAndroidArtifact { }

可以看到PackageApplication繼承類PackageAndroidArtifact,任務入口集中在基類

//PackageAndroidArtifact.java @Override protected void doFullTaskAction() {// check that we don't have colliding output file namescheckFileNameUniqueness();ExistingBuildElements.from(getTaskInputType(), resourceFiles).transform((ApkInfo apkInfo, File inputFile) -> {try {return splitFullAction(apkInfo, inputFile);} catch (IOException e) {throw new BuildException(e.getMessage(), e);}}).into(getInternalArtifactType(), outputDirectory);}

可以看到方法最終調用splitFullAction方法

public File splitFullAction(@NonNull ApkInfo apkData, @Nullable File processedResources)throws IOException {File incrementalDirForSplit = new File(getIncrementalFolder(), apkData.getFullName());/** Clear the intermediate build directory. We don't know if anything is in there and* since this is a full build, we don't want to get any interference from previous state.*/if (incrementalDirForSplit.exists()) {FileUtils.deleteDirectoryContents(incrementalDirForSplit);} else {FileUtils.mkdirs(incrementalDirForSplit);}File cacheByPathDir = new File(incrementalDirForSplit, ZIP_DIFF_CACHE_DIR);FileUtils.mkdirs(cacheByPathDir);FileCacheByPath cacheByPath = new FileCacheByPath(cacheByPathDir);/** Clear the cache to make sure we have do not do an incremental build.*/cacheByPath.clear();Set<File> androidResources = getAndroidResources(processedResources);FileUtils.mkdirs(outputDirectory);BuildOutput buildOutput = computeBuildOutputFile(apkData);File outputFile = buildOutput.getOutputFile();/** Additionally, make sure we have no previous package, if it exists.*/FileUtils.deleteIfExists(outputFile);final ImmutableMap<RelativeFile, FileStatus> updatedDex;final ImmutableMap<RelativeFile, FileStatus> updatedJavaResources;if (!hasFeatureDexFiles()) {// 1. 讀取dex文件(合并后的)updatedDex = IncrementalRelativeFileSets.fromZipsAndDirectories(getDexFolders());// 2. 加載標準java資源文件(eg:0.jar)updatedJavaResources = getJavaResourcesChanges();} else {// We reach this code if we're in a feature module and minification is enabled in the// base module. In this case, we want to use the classes.dex file from the base// module's DexSplitterTransform.checkNotNull(getFeatureDexFolder());updatedDex = IncrementalRelativeFileSets.fromZipsAndDirectories(getFeatureDexFolder());// For now, java resources are in the base apk, so we exclude them here (b/77546738)updatedJavaResources = ImmutableMap.of();}// 3. 加載merged后的assets文件ImmutableMap<RelativeFile, FileStatus> updatedAssets =IncrementalRelativeFileSets.fromZipsAndDirectories(assets.getFiles());// 4. 加載android資源庫文件(eg:resources-debug*.ap_)ImmutableMap<RelativeFile, FileStatus> updatedAndroidResources =IncrementalRelativeFileSets.fromZipsAndDirectories(androidResources);// 5. so相關文件ImmutableMap<RelativeFile, FileStatus> updatedJniResources =IncrementalRelativeFileSets.fromZipsAndDirectories(getJniFolders());// 6. 清合后的清單文件BuildElements manifestOutputs = ExistingBuildElements.from(manifestType, manifests);// 7. 打包成apk,最終是通過一個叫ApkZFileCreator類進行打包的doTask(apkData,incrementalDirForSplit,outputFile,cacheByPath,manifestOutputs,updatedDex,updatedJavaResources,updatedAssets,updatedAndroidResources,updatedJniResources);/** Update the known files.*/KnownFilesSaveData saveData = KnownFilesSaveData.make(incrementalDirForSplit);saveData.setInputSet(updatedDex.keySet(), InputSet.DEX);saveData.setInputSet(updatedJavaResources.keySet(), InputSet.JAVA_RESOURCE);saveData.setInputSet(updatedAssets.keySet(), InputSet.ASSET);saveData.setInputSet(updatedAndroidResources.keySet(), InputSet.ANDROID_RESOURCE);saveData.setInputSet(updatedJniResources.keySet(), InputSet.NATIVE_RESOURCE);saveData.saveCurrentData();recordMetrics(outputFile, processedResources);return outputFile; }

👇
Android構建流程——上篇

總結

以上是生活随笔為你收集整理的Android构建流程——篇八的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。