Android AspectJX 適配Gradle 4.10.1

問題

前段時間Android Studio的版本升級到了3.x,Gradle 的版本也升級到了4.x +,問題來了,以前在項目中使用了Aspectjx這個gradle插件,但在新的環境中,sync gradle的時候,報錯了:java

WARNING: API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance
Affected Modules: app
複製代碼

這是因爲Gradle升級後,getJavaCompile()方法已經被廢棄,因此在新的版本里會提示出使用新的API的警告,雖然是Warning,但其實已經沒法正常構建腳本了,問題腳本以下:android

variants.all { variant ->
    //--------------------------------問題位置-------------------------
    JavaCompile javaCompile = variant.javaCompile //******問題代碼
    //--------------------------------問題位置-------------------------
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)
    }
}
複製代碼

解決

0、瞭解這個Warning發生的位置,源碼以下:緩存

@Override
@NonNull
public JavaCompile getJavaCompile() {
    BaseVariantData variantData = getVariantData();
    variantData
            .getScope()
            .getGlobalScope()
            .getDslScope()
            .getDeprecationReporter()
            .reportDeprecatedApi(
                    "variant.getJavaCompileProvider()",
                    "variant.getJavaCompile()",
                    TASK_ACCESS_DEPRECATION_URL,
                    DeprecationReporter.DeprecationTarget.TASK_ACCESS_VIA_VARIANT);
    return variantData.getTaskContainer().getJavacTask().get();
}
複製代碼

就是說在Gradle 4.10.1版本中,當使用getJavaCompile(),會直接執行reportDeprecatedApi(),發出一個警告,後面的retrun也就不會正常執行了。app

一、顯然須要將使用variant.getJavaCompile()的地方改成variant.getJavaCompileProvider() 首先,我找到getJavaCompileProvider()的源碼,發現返回值不是直接返回JavaCompile對象,而是TaskProvider<JavaCompile>對象:maven

@NonNull
@Override
public TaskProvider<JavaCompile> getJavaCompileProvider() {
    //noinspection unchecked
    return (TaskProvider<JavaCompile>) getVariantData().getTaskContainer().getJavacTask();
}
複製代碼

這是一個JavaCompile的封裝類,能夠經過get()方法獲取到JavaCompile對象:ide

TaskProvider<JavaCompile> provider =  variant.javaCompileProvider
javaCompile = provider.get()
複製代碼

二、因此以前出問題的腳本能夠修改以下:gradle

variants.all { variant ->
    //--------------------------------問題位置-------------------------
    JavaCompile javaCompile = variant.javaCompile //******問題代碼
    //--------------------------------修復後的代碼-------------------
    JavaCompile javaCompile = null
        if (variant.hasProperty('javaCompileProvider')) {
            //gradle 4.10.1 +
            TaskProvider<JavaCompile> provider =  variant.javaCompileProvider
            javaCompile = provider.get()
        } else {
            javaCompile = variant.hasProperty('javaCompiler') ? variant.javaCompiler : variant.javaCompile
        }
    //--------------------------------修復後的代碼-----------------------
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)
    }
}
複製代碼

首先,判斷是否存在javaCompileProvider,若是存在就使用新的API,若是不存在就說明腳本的運行環境仍是老的Gradle版本,這裏又加了一個判斷是否有javaCompiler,這是適配更老的版本,這樣寫起來更加嚴謹一些。ui

以上就是Aspectj適配Gradle4.x的部分,可是,個人項目使用了Aspectjx這個插件,當時只是爲了讓gradle腳本看起來乾淨些,也不用維護,但目前這個項目貌似並無修復這個問題,若是換成本身寫,但也能夠,就是折騰,我這人懶,習慣一勞永逸,因而決定本身改AspectJx的源碼,而後本身打包上傳到maven上,目前已經完成,源碼以下:lua

/**
 * class description here
 * @author simon
 * @version 1.0.0
 * @since 2018-04-20
 */
class AJXProcedure extends AbsProcedure {

    Project project
    AJXCache ajxCache

    AJXProcedure(Project proj) {
        super(proj, null, null)

        project = proj
        ajxCache = new AJXCache(project)

        System.setProperty("aspectj.multithreaded", "true")

        def configuration = new AJXConfig(project)

        project.afterEvaluate {

            configuration.variants.all { variant ->
                JavaCompile javaCompile = null
                if (variant.hasProperty('javaCompileProvider')) {
                    //gradle 4.10.1 +
                    TaskProvider<JavaCompile> provider =  variant.javaCompileProvider
                    javaCompile = provider.get()
                } else {
                    javaCompile = variant.hasProperty('javaCompiler') ? variant.javaCompiler : variant.javaCompile

                }
                ajxCache.encoding = javaCompile.options.encoding
                ajxCache.bootClassPath = configuration.bootClasspath.join(File.pathSeparator)
                ajxCache.sourceCompatibility = javaCompile.sourceCompatibility
                ajxCache.targetCompatibility = javaCompile.targetCompatibility
            }


            AJXExtension ajxExtension = project.aspectjx
            //當過濾條件發生變化,clean掉編譯緩存
            if (ajxCache.isExtensionChanged(ajxExtension)) {
                project.tasks.findByName('preBuild').dependsOn(project.tasks.findByName("clean"))
            }

            ajxCache.putExtensionConfig(ajxExtension)

            ajxCache.ajcArgs = ajxExtension.ajcArgs
        }

        //set aspectj build log output dir
        File logDir = new File(project.buildDir.absolutePath + File.separator + "outputs" + File.separator + "logs")
        if (!logDir.exists()) {
            logDir.mkdirs()
        }

        Dump.setDumpDirectory(logDir.absolutePath)
    }
}
複製代碼

我目前上傳到了公司的私服在使用,有時間修改一個能夠開源的版本(公司管的嚴格)。spa

相關文章
相關標籤/搜索