溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android開發(fā)升級AGP7.0后的適配方法有哪些

發(fā)布時間:2022-06-23 09:28:43 來源:億速云 閱讀:445 作者:iii 欄目:開發(fā)技術

本文小編為大家詳細介紹“Android開發(fā)升級AGP7.0后的適配方法有哪些”,內容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“Android開發(fā)升級AGP7.0后的適配方法有哪些”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

    升級

    年初了,我們打算升級下apg,這樣之后就擁抱下jetpack compose了?。?/p>

    想用comopse有兩個必選項agp7.0和kotlin版本1.5.31.

    Java11配置

    因為apg7.0需要把所有的module編譯環(huán)境切換到java11版本上,然而這個地方很容易出錯。

    首先是命令行的配置,對于mac用戶來說,可能會寫死默認的java環(huán)境到1.8. 這個時候我們需要做的就是刪除bashprofile內的java配置。

    同時最好用命令行java --version嘗試下輸出的版本是不是java11。

    Android開發(fā)升級AGP7.0后的適配方法有哪些

    as的配置則相對來說比較簡單了。

    Android開發(fā)升級AGP7.0后的適配方法有哪些

    Android開發(fā)升級AGP7.0后的適配方法有哪些

    按照這兩個配置完成之后重新同步下工程應該就行了。

    AndroidComponentsExtension

    之前在現在準備好告別Transform了嗎?的文章就簡單展開了下AndroidComponentsExtension,新版本更換了extensions。這次給項目升級適配之前寫的哪些插件,想了想用新不用久嗎,嘗試下新東西了。

    onVariants

    以前在寫android插件的時候很多時候都需要在gralde的afterEvaluate方法執(zhí)行之后才能獲取到很多安卓對應的屬性。

    這次在v2的api中,則提供了非常多不同的節(jié)點,讓我們在不同的階段做一些不同的事情。

    比如說onVariants,beforeVariants,finalizeDsl這三個不同的階段,正常情況下我們選擇onVariants就足夠了。

    Component Artifacts

    demo 地址

    Gralde 內的一部分核心是Task,但是要想寫好一個Task其實并沒有想象中的那么容易。特別是一個CacheableTask,他更多的關注與他們的輸入和輸出。

    構建緩存(build cache)的工作原理是:在緩存中存儲已編譯的類、測試輸出和其他構建構件,同時考慮所有的任務輸入,包括輸入文件內容、相關類路徑和任務配置。

    所以在AGP 7.0中,提供了這部分新的api讓我們簡化對于task,輸入輸出這些參數的優(yōu)化,讓我們可以更專注到我們想要變更的東西上。

    比如說APk,MANIFEST,MAPPING_FILE,BUNDLE,AAR或者其他的一些編譯產物,當前agp給我們提供的也是相對來說比較少的一部分功能。

    另外一點就是,我們如果想要知道一個task的輸入其實如果不去閱讀源碼,之后獲取對應的路徑或者源代碼,其實是一個非常繁瑣的過程。之后還要通過變更dependon或者finalizedBy等等手段將任務插入到編譯流程內。

    所以就有了我們這次的其中一個主角Artifacts,他主要負責幫助我們將我們的task,插入到編譯流程內,讓我們盡量少的關注到輸入和輸出。

              // 生成TaskProvider 
              val taskProvider = project.tasks.register(
                      "manifestCopy${variant.name}Task",
                      ManifestSampleTask::class.java
              )
              // 獲取variant的artifacts之后將Task轉化成我們所想要的
              variant.artifacts.use(taskProvider).wiredWithFiles(
                      ManifestSampleTask::mergedManifest,
                      ManifestSampleTask::outputManifest
              ).toTransform(SingleArtifact.MERGED_MANIFEST)

    這個就是官方的一個Artifacts的簡單的使用了,通過變化我們可以輕松的完成一個有獲取合并后的Manifest作為輸入,之后以另外一個Manifest文件作為輸出的一個task。而且會被直接添加編譯流程內,就不需要我們關心他們的前置和后置任務是啥了。

    registerJavaGenerateTask 沒了

    原先在v1的api上吧,有registerJavaGenerateTask這個方法,能加一些簡單的代碼生成的操作,比如j神以前生成的R2就是通過掛載這個方法。

    這次v2版本我在AndroidComponentsExtension中沒找到的對應的api,所以只能無中生友,自己搞一個出來咯。

    @Override
     public void registerJavaGeneratingTask(@NonNull Task task, @NonNull File... sourceFolders) {
         getVariantData().registerJavaGeneratingTask(task, sourceFolders);
     }
     open fun registerJavaGeneratingTask(
        task: Task,
        generatedSourceFolders: Collection<File>
    ) {
        @Suppress("DEPRECATION")
        taskContainer.sourceGenTask.dependsOn(task)
        val fileTrees = extraGeneratedSourceFileTrees ?: mutableListOf<ConfigurableFileTree>().also {
            extraGeneratedSourceFileTrees = it
        }
        for (f in generatedSourceFolders) {
            val fileTree = services.fileTree(f).builtBy(task)
            fileTrees.add(fileTree)
        }
        addJavaSourceFoldersToModel(generatedSourceFolders)
    }

    我仔細觀察了下registerJavaGenerateTask的源代碼,發(fā)現其中只做了兩件比較簡單的事情。將Task掛載到generateVariantResources任務之后,然后將生成java類的文件夾加入到sourcetSet上去,這樣就行了。

    sourcetSet就是javac的將java轉化成class的編譯路徑。

    所以相對來說就比較簡單,我們用新的api模擬出原來的效果就差不多可以了,我們只要找到掛載的任務之后,順便把代碼添加到java和kotlin的sourceset中就行了

    fun Project.registerJavaGenerateTask(
        variant: String?,
        task: TaskProvider<out Task>,
        generatedSourceFolders: Collection<File>
    ) {
        if (variant.isNullOrEmpty().not()) {
            variant?.apply {
                // 因為task生成在配置階段完成之后
                afterEvaluate {
                    findJavaGenerateTask(variant)?.dependsOn(task)
                }
                //  獲取最新版本sourceSet
                val application = extensions.findByType(ApplicationExtension::class.java)
                application?.sourceSets {
                    findByName(variant)?.apply {
                        generatedSourceFolders.forEach {
                            java.srcDir(it)
                            kotlin.srcDir(it)
                        }
                    }
                }
            }
        }
    }

    這次升級適配主要的代碼就是這個了,其實代碼量上來說不多。但是把有個坑點,之前因為偷懶就直接用了setSrcDirs這個api,所以文件就被覆蓋了。導致了一部分代碼沒有被編譯成class,導致了classnotfound異常。

    其他

    獲取applicationId,我們的插件內有對于應用id的判斷,之后進行不同的manifest pleaceholder的調整。邏輯比較簡單,只是切換了新版本的api而已。

      if (variant is ApplicationVariant) {
        val applicationId = variant.applicationId.get()
          variant.manifestPlaceholders.put("xxxxx", applicationId)
      }

    對resValue插入新的string或者values。也是原來就有的能力,但是要對新版本進行一次小小的適配和更換。

    private fun addAPGClassFile(config: Variant, key: String, value: String) {
        val resValue = ResValue(value)
        val reskey = config.makeResValueKey("string", key)
        config.resValues.put(reskey, resValue)
    }

    啟動configuration cache

    啟用配置緩存的操作,本質上是在項目的 gradle.properties 文件中設置了環(huán)境變量 org.gradle.unsafe.configuration-cache=true。

    讀到這里,這篇“Android開發(fā)升級AGP7.0后的適配方法有哪些”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業(yè)資訊頻道。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI