从Android Plugin源码开始彻底理解gradle构建:Extension(二)

本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

系列文章: 

从Android Plugin源码开始彻底理解gradle构建:初识AndroidDSL(一)

一、前言回顾

        上回我们说到Android plugin的所有自定义plugin都需要重写的apply方法,并讲到该方法里最为重要的三个回调方法,我们回顾一下:

            //plugin的基础设置、初始化工作
            threadRecorder.record(  
                    ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,  
                    project.getPath(),  
                    null,  
                    this::configureProject);  
            //EXTENSION的初始化工作
            threadRecorder.record(  
                    ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,  
                    project.getPath(),  
                    null,  
                    this::configureExtension);  
             //plugin的task创建
            threadRecorder.record(  
                    ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,  
                    project.getPath(),  
                    null,  
                    this::createTasks); 

上一篇文章我们简单讲解第一个初始化方法,今天我们的主角就是第二个configureExtension方法

Extension究竟是什么?就我理解,可以把gradle的Extension比喻为JAVA的成员变量。虽然不完全相同,但是也有相似之处,何出此言?让我们继续往下看。

二、Extension介绍

讲解之前我们先看一段熟悉的代码:

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.gradletest"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

相信这段代码在座的各位都看吐了吧?

是的,笔者也一样。刚开始接触AS的时候,看这段代码感觉就感觉在看天书,反正按规定配置就对了。今天我们就把他扒光了看看有什么特别。

仔细观察其实也比较好理解,就是android的一些配置:

compileSdkVersion指的是当前的androidSDK版本、applicationId指的是包名、versionCode指的是版本号....balabala...

虽然经过几年的百度、谷歌熏陶已经很熟悉了,但是为什么这么配置呢?接下来就为各位看官解答。


我们可以把一个gradle项目看做一个Project,而这个Project就类似JAVA的类,而一个类自然就需要成员变量咯,所以我们首先就来创建一个pojo类,就命名为Person吧:

public class Person {

    String name;

    int age;

    @Override
    public String toString() {
        return "I am $name, $age years old"
    }
}

然后就像上篇文章那样创建一个自定义插件:

class MyPlugin implements Plugin<Project>{   
    @Override   
    void apply(Project project) {        
         project.extensions.add("person", Person)
         project.task('printPerson') {
            group 'atom'
            doLast{
             Person ext = project.person
             println ext 
          }
       }
  }  
}  
第一句调用了project的extensions,他可以视为变量的容器,只要往里加就OK了,然后就可以通过project调用到person了

第二句是我们下节需要讲到的内容,可以暂时无视,直接看dolast里面的代码就好了

很简单,我直接打印了该person,接下来就是重点了,我们需要在build.gradle里面配置person

person{
    name  'atom'
    age  18
}

是不是就像android的标签一样?这下应该很好理解gradle里为何这么写了吧。

其实这里就相当于我们给person做了初始化,只是用有些像json的写法而已。

不过这样我们就可以配置项目参数了,是不是很方便?

我们来验证一下,执行一下gradle printPerson命令:


如我们所想,打印了我们配置的18岁的atom:)

三、Android的Extension

有了基础的认识,让我们回到文章开头的configureExtension方法:
    private void configureExtension() {
        ObjectFactory objectFactory = project.getObjects();
        //1==============
        final NamedDomainObjectContainer<BuildType> buildTypeContainer =
                project.container(
                        BuildType.class,
                        new BuildTypeFactory(
                                objectFactory,
                                project,
                                extraModelInfo.getSyncIssueHandler(),
                                extraModelInfo.getDeprecationReporter()));
        final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer =
                project.container(
                        ProductFlavor.class,
                        new ProductFlavorFactory(
                                objectFactory,
                                project,
                                extraModelInfo.getDeprecationReporter(),
                                project.getLogger()));
        final NamedDomainObjectContainer<SigningConfig> signingConfigContainer =
                project.container(
                        SigningConfig.class,
                        new SigningConfigFactory(
                                objectFactory,
                                GradleKeystoreHelper.getDefaultDebugKeystoreLocation()));

        final NamedDomainObjectContainer<BaseVariantOutput> buildOutputs =
                project.container(BaseVariantOutput.class);

        project.getExtensions().add("buildOutputs", buildOutputs);

        sourceSetManager = createSourceSetManager();
        //2==============
        extension =
                createExtension(
                        project,
                        projectOptions,
                        androidBuilder,
                        sdkHandler,
                        buildTypeContainer,
                        productFlavorContainer,
                        signingConfigContainer,
                        buildOutputs,
                        sourceSetManager,
                        extraModelInfo);


        ndkHandler =
                new NdkHandler(
                        project.getRootDir(),
                        null, /* compileSkdVersion, this will be set in afterEvaluate */
                        "gcc",
                        "" /*toolchainVersion*/,
                        false /* useUnifiedHeaders */);




        @Nullable
        FileCache buildCache = BuildCacheUtils.createBuildCacheIfEnabled(project, projectOptions);


        GlobalScope globalScope =
                new GlobalScope(
                        project,
                        projectOptions,
                        androidBuilder,
                        extension,
                        sdkHandler,
                        ndkHandler,
                        registry,
                        buildCache);

        //3===============================
        variantFactory = createVariantFactory(globalScope, androidBuilder, extension);


        taskManager =
                createTaskManager(
                        globalScope,
                        project,
                        projectOptions,
                        androidBuilder,
                        dataBindingBuilder,
                        extension,
                        sdkHandler,
                        ndkHandler,
                        registry,
                        threadRecorder);


        variantManager =
                new VariantManager(
                        globalScope,
                        project,
                        projectOptions,
                        androidBuilder,
                        extension,
                        variantFactory,
                        taskManager,
                        sourceSetManager,
                        threadRecorder);

        //省略部分代码
        // create default Objects, signingConfig first as its used by the BuildTypes.
        variantFactory.createDefaultComponents(
                buildTypeContainer, productFlavorContainer, signingConfigContainer);
    }


1、首先创建了四个NamedDomainObjectContainer,是由project的Container方法返回的,这些东东是什么有什么用,光靠百度谷歌基本上是很难找到了(笔者写这篇文章的时候gradle方面的资料还是相当匮乏的),所以我们得学会看官方文档咯~

也不算太难,笔者这二流英语水平都能看懂:创建一个容器,用来管理泛型中定义的类。而factory自然就是创建该类的工厂了。

所以根据上诉代码,不难知道创建了BuildType、ProductFlavor、SigningConfig、BaseVariantOutput这四个类的容器了。

稍微熟悉构建的童鞋应该很清楚这几个类的用处:

buildType

构建类型,在Android Gradle工程中,它已经帮我们内置了debug和release两个构建类型,可以分别设置不同包名等信息。

signingConfigs

签名配置,可以设置debug和release甚至自定义方式时的不同keystore,及其密码等信息。

ProductFlavor

多渠道打包必备,用处很多笔者也有推荐文章介绍

而最后一个BaseVariantOutput,“望文生义“不难才到就是输出文件咯~


2、把project、androidBuilder以及刚刚提到的几个类作为参数创建了extension,这里使用了策略模式,createExtension是一个抽象方法,真正实现是在AppPlugin

    protected BaseExtension createExtension(
            @NonNull Project project,
            @NonNull ProjectOptions projectOptions,
            @NonNull AndroidBuilder androidBuilder,
            @NonNull SdkHandler sdkHandler,
            @NonNull NamedDomainObjectContainer<BuildType> buildTypeContainer,
            @NonNull NamedDomainObjectContainer<ProductFlavor> productFlavorContainer,
            @NonNull NamedDomainObjectContainer<SigningConfig> signingConfigContainer,
            @NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,
            @NonNull SourceSetManager sourceSetManager,
            @NonNull ExtraModelInfo extraModelInfo) {
        return project.getExtensions()
                .create(
                        "android",
                        AppExtension.class,
                        project,
                        projectOptions,
                        androidBuilder,
                        sdkHandler,
                        buildTypeContainer,
                        productFlavorContainer,
                        signingConfigContainer,
                        buildOutputs,
                        sourceSetManager,
                        extraModelInfo);
    }

就如同我们之前介绍创建Extension的方式一样,通过project创建了名为“android”的Extension,类型为AppExtension,这个类就包含了我们平时用到的版本号、包名等等信息,为我们构建项目打下了基础。

3、用同样的方式创建了variantFactory、taskManager、variantManager,最后设置了默认的构建信息。

关于这几个类的作用分别是:

variantFactory构建信息的工厂、taskManager构建任务、variantManager各种不同构建方式及多渠道构建的管理

这就涉及到gradle核心:task了,也是下一篇文章需要讲的内容,大家敬请关注。


四、结语

本文主要介绍了build中配置信息写法的由来,让大家看到配置信息时不再那么没有底气。

不知道大家有没有发现,我例子中使用的groovy语法来写插件,而Android Plugin确是使用Java来写的

具体原因不明,但是可以看出,groovy是完全兼容Java的,如果你想的话甚至可以使用kotlin来写,最新版本的AndroidDSL也加入了kotlin代码。但是还是推荐学习groovy的基本用法,毕竟也有喜欢使用groovy来写插件的,我们得看的懂对吧,比如virtualAPK~


A problem occurred evaluating project ':tess-two'. > Could not find method publications() for arguments [build_cbf15uup5mups67kcekw2jm8o$_run_closure1$_closure10$_closure14@1618a70f] on object of type com.android.build.gradle.internal.dsl.LibraryPublishingImpl$AgpDecorated. * Try: > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. * Exception is: org.gradle.api.GradleScriptException: A problem occurred evaluating project ':tess-two'. at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:93) at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.lambda$apply$1(DefaultScriptPluginFactory.java:143) at org.gradle.configuration.ProjectScriptTarget.addConfiguration(ProjectScriptTarget.java:79) at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:146) at org.gradle.configuration.BuildOperationScriptPlugin$1.run(BuildOperationScriptPlugin.java:68) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47) at org.gradle.configuration.BuildOperationScriptPlugin.lambda$apply$0(BuildOperationScriptPlugin.java:65) at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:44) at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:65) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:411) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:429) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:410) at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:46) at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:27) at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35) at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.lambda$run$0(LifecycleProjectEvaluator.java:109) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$applyToMutableState$1(DefaultProjectStateRegistry.java:411) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.lambda$fromMutableState$2(DefaultProjectStateRegistry.java:434) at org.gradle.internal.work.DefaultWorkerLeaseService.withReplacedLocks(DefaultWorkerLeaseService.java:359) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.fromMutableState(DefaultProjectStateRegistry.java:434) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.applyToMutableState(DefaultProjectStateRegistry.java:410) at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:100) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47) at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:72) at org.gradle.api.internal.project.DefaultProject.evaluateUnchecked(DefaultProject.java:825) at org.gradle.api.internal.project.ProjectLifecycleController.lambda$ensureSelfConfigured$2(ProjectLifecycleController.java:85) at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255) at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266) at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254) at org.gradle.internal.model.StateTransitionController.lambda$maybeTransitionIfNotCurrentlyTransitioning$10(StateTransitionController.java:199) at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:36) at org.gradle.internal.model.StateTransitionController.maybeTransitionIfNotCurrentlyTransitioning(StateTransitionController.java:195) at org.gradle.api.internal.project.ProjectLifecycleController.ensureSelfConfigured(ProjectLifecycleController.java:85) at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.ensureConfigured(DefaultProjectStateRegistry.java:385) at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:42) at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:58) at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:50) at org.gradle.configuration.BuildTreePreparingProjectsPreparer.prepareProjects(BuildTreePreparingProjectsPreparer.java:65) at org.gradle.configuration.BuildOperationFiringProjectsPreparer$ConfigureBuild.run(BuildOperationFiringProjectsPreparer.java:52) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29) at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47) at org.gradle.configuration.BuildOperationFiringProjectsPreparer.prepareProjects(BuildOperationFiringProjectsPreparer.java:40) at org.gradle.initialization.VintageBuildModelController.lambda$prepareProjects$2(VintageBuildModelController.java:84) at org.gradle.internal.model.StateTransitionController.lambda$doTransition$14(StateTransitionController.java:255) at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266) at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:254) at org.gradle.internal.model.StateTransitionController.lambda$transitionIfNotPreviously$11(StateTransitionController.java:213) at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:36) at org.gradle.internal.model.StateTransitionController.transitionIfNotPreviously(StateTransitionController.java:209) at org.gradle.initialization.VintageBuildModelController.prepareProjects(VintageBuildModelController.java:84) at org.gradle.initialization.VintageBuildModelController.getConfiguredModel(VintageBuildModelController.java:64) at org.gradle.internal.build.DefaultBuildLifecycleController.lambda$withProjectsConfigured$1(DefaultBuildLifecycleController.java:133) at org.gradle.internal.model.StateTransitionController.lambda$notInState$3(StateTransitionController.java:132) at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:46) at org.gradle.internal.model.StateTransitionController.notInState(StateTransitionController.java:128) at org.gradle.internal.build.DefaultBuildLifecycleController.withProjectsConfigured(DefaultBuildLifecycleController.java:133) at org.gradle.internal.build.DefaultBuildToolingModelController.locateBuilderForTarget(DefaultBuildToolingModelController.java:58) at org.gradle.internal.buildtree.DefaultBuildTreeModelCreator$DefaultBuildTreeModelController.lambda$locateBuilderForTarget$0(DefaultBuildTreeModelCreator.java:64) at org.gradle.internal.build.DefaultBuildLifecycleController.withToolingModels(DefaultBuildLifecycleController.java:327) at org.gradle.internal.build.AbstractBuildState.withToolingModels(AbstractBuildState.java:160) at org.gradle.internal.buildtree.DefaultBuildTreeModelCreator$DefaultBuildTreeModelController.locateBuilderForTarget(DefaultBuildTreeModelCreator.java:64) at org.gradle.internal.buildtree.DefaultBuildTreeModelCreator$DefaultBuildTreeModelController.locateBuilderForDefaultTarget(DefaultBuildTreeModelCreator.java:59) at org.gradle.tooling.internal.provider.runner.DefaultBuildController.getTarget(DefaultBuildController.java:140) at org.gradle.tooling.internal.provider.runner.DefaultBuildController.getModel(DefaultBuildController.java:111) at org.gradle.tooling.internal.consumer.connection.ParameterAwareBuildControllerAdapter.getModel(ParameterAwareBuildControllerAdapter.java:40) at org.gradle.tooling.internal.consumer.connection.UnparameterizedBuildController.getModel(UnparameterizedBuildController.java:116) at org.gradle.tooling.internal.consumer.connection.NestedActionAwareBuildControllerAdapter.getModel(NestedActionAwareBuildControllerAdapter.java:32) at org.gradle.tooling.internal.consumer.connection.UnparameterizedBuildController.getModel(UnparameterizedBuildController.java:79) at org.gradle.tooling.internal.consumer.connection.NestedActionAwareBuildControllerAdapter.getModel(NestedActionAwareBuildControllerAdapter.java:32) at org.gradle.tooling.internal.consumer.connection.UnparameterizedBuildController.getModel(UnparameterizedBuildController.java:64) at org.gradle.tooling.internal.consumer.connection.NestedActionAwareBuildControllerAdapter.getModel(NestedActionAwareBuildControllerAdapter.java:32) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.lambda$initAction$6(GradleModelFetchAction.java:185) at com.intellij.gradle.toolingExtension.impl.telemetry.GradleOpenTelemetry.callWithSpan(GradleOpenTelemetry.java:74) at com.intellij.gradle.toolingExtension.impl.telemetry.GradleOpenTelemetry.callWithSpan(GradleOpenTelemetry.java:62) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.initAction(GradleModelFetchAction.java:184) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.doExecute(GradleModelFetchAction.java:139) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.lambda$execute$1(GradleModelFetchAction.java:104) at com.intellij.gradle.toolingExtension.impl.telemetry.GradleOpenTelemetry.callWithSpan(GradleOpenTelemetry.java:74) at com.intellij.gradle.toolingExtension.impl.telemetry.GradleOpenTelemetry.callWithSpan(GradleOpenTelemetry.java:62) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.lambda$execute$2(GradleModelFetchAction.java:103) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.withOpenTelemetry(GradleModelFetchAction.java:114) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.lambda$execute$3(GradleModelFetchAction.java:102) at com.intellij.gradle.toolingExtension.impl.util.GradleExecutorServiceUtil.withSingleThreadExecutor(GradleExecutorServiceUtil.java:18) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.execute(GradleModelFetchAction.java:101) at com.intellij.gradle.toolingExtension.impl.modelAction.GradleModelFetchAction.execute(GradleModelFetchAction.java:37) at org.gradle.tooling.internal.consumer.connection.InternalBuildActionAdapter.execute(InternalBuildActionAdapter.java:65) at org.gradle.tooling.internal.provider.runner.AbstractClientProvidedBuildActionRunner$ActionAdapter.executeAction(AbstractClientProvidedBuildActionRunner.java:109) at org.gradle.tooling.internal.provider.runner.AbstractClientProvidedBuildActionRunner$ActionAdapter.runAction(AbstractClientProvidedBuildActionRunner.java:97) at org.gradle.tooling.internal.provider.runner.AbstractClientProvidedBuildActionRunner$ActionAdapter.beforeTasks(AbstractClientProvidedBuildActionRunner.java:81) at org.gradle.internal.buildtree.DefaultBuildTreeModelCreator.beforeTasks(DefaultBuildTreeModelCreator.java:43) at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$fromBuildModel$2(DefaultBuildTreeLifecycleController.java:83) at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.lambda$runBuild$4(DefaultBuildTreeLifecycleController.java:120) at org.gradle.internal.model.StateTransitionController.lambda$transition$6(StateTransitionController.java:169) at org.gradle.internal.model.StateTransitionController.doTransition(StateTransitionController.java:266) at org.gradle.internal.model.StateTransitionController.lambda$transition$7(StateTransitionController.java:169) at org.gradle.internal.work.DefaultSynchronizer.withLock(DefaultSynchronizer.java:46) at org.gradle.internal.model.StateTransitionController.transition(StateTransitionController.java:169) at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.runBuild(DefaultBuildTreeLifecycleController.java:117) at org.gradle.internal.buildtree.DefaultBuildTreeLifecycleController.fromBuildModel(DefaultBuildTreeLifecycleController.java:82) at org.gradle.tooling.internal.provider.runner.AbstractClientProvidedBuildActionRunner.runClientAction(AbstractClientProvidedBuildActionRunner.java:43) at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:59) at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) at org.gradle.internal.buildtree.ProblemReportingBuildActionRunner.run(ProblemReportingBuildActionRunner.java:49) at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:66) at org.gradle.tooling.internal.provider.FileSystemWatchingBuildActionRunner.run(FileSystemWatchingBuildActionRunner.java:140) at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:41) at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.lambda$execute$0(RootBuildLifecycleBuildActionExecutor.java:54) at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:130) at org.gradle.launcher.exec.RootBuildLifecycleBuildActionExecutor.execute(RootBuildLifecycleBuildActionExecutor.java:54) at org.gradle.internal.buildtree.InitDeprecationLoggingActionExecutor.execute(InitDeprecationLoggingActionExecutor.java:62) at org.gradle.internal.buildtree.InitProblems.execute(InitProblems.java:36) at org.gradle.internal.buildtree.DefaultBuildTreeContext.execute(DefaultBuildTreeContext.java:40) at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.lambda$execute$0(BuildTreeLifecycleBuildActionExecutor.java:71) at org.gradle.internal.buildtree.BuildTreeState.run(BuildTreeState.java:60) at org.gradle.launcher.exec.BuildTreeLifecycleBuildActionExecutor.execute(BuildTreeLifecycleBuildActionExecutor.java:71) at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$3.call(RunAsBuildOperationBuildActionExecutor.java:61) at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor$3.call(RunAsBuildOperationBuildActionExecutor.java:57) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209) at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66) at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166) at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59) at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53) at org.gradle.launcher.exec.RunAsBuildOperationBuildActionExecutor.execute(RunAsBuildOperationBuildActionExecutor.java:57) at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.lambda$execute$0(RunAsWorkerThreadBuildActionExecutor.java:36) at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:263) at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:127) at org.gradle.launcher.exec.RunAsWorkerThreadBuildActionExecutor.execute(RunAsWorkerThreadBuildActionExecutor.java:36) at org.gradle.tooling.internal.provider.continuous.ContinuousBuildActionExecutor.execute(ContinuousBuildActionExecutor.java:110) at org.gradle.tooling.internal.provider.SubscribableBuildActionExecutor.execute(SubscribableBuildActionExecutor.java:64) at org.gradle.internal.session.DefaultBuildSessionContext.execute(DefaultBuildSessionContext.java:46) at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor$ActionImpl.apply(BuildSessionLifecycleBuildActionExecutor.java:92) at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor$ActionImpl.apply(BuildSessionLifecycleBuildActionExecutor.java:80) at org.gradle.internal.session.BuildSessionState.run(BuildSessionState.java:71) at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor.execute(BuildSessionLifecycleBuildActionExecutor.java:62) at org.gradle.internal.buildprocess.execution.BuildSessionLifecycleBuildActionExecutor.execute(BuildSessionLifecycleBuildActionExecutor.java:41) at org.gradle.internal.buildprocess.execution.StartParamsValidatingActionExecutor.execute(StartParamsValidatingActionExecutor.java:64) at org.gradle.internal.buildprocess.execution.StartParamsValidatingActionExecutor.execute(StartParamsValidatingActionExecutor.java:32) at org.gradle.internal.buildprocess.execution.SessionFailureReportingActionExecutor.execute(SessionFailureReportingActionExecutor.java:51) at org.gradle.internal.buildprocess.execution.SessionFailureReportingActionExecutor.execute(SessionFailureReportingActionExecutor.java:39) at org.gradle.internal.buildprocess.execution.SetupLoggingActionExecutor.execute(SetupLoggingActionExecutor.java:47) at org.gradle.internal.buildprocess.execution.SetupLoggingActionExecutor.execute(SetupLoggingActionExecutor.java:31) at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:70) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:29) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.lambda$execute$0(ForwardClientInput.java:40) at org.gradle.internal.daemon.clientinput.ClientInputForwarder.forwardInput(ClientInputForwarder.java:80) at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:64) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:84) at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37) at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104) at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52) at org.gradle.launcher.daemon.server.DaemonStateCoordinator.lambda$runCommand$0(DaemonStateCoordinator.java:321) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48) Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method publications() for arguments [build_cbf15uup5mups67kcekw2jm8o$_run_closure1$_closure10$_closure14@1618a70f] on object of type com.android.build.gradle.internal.dsl.LibraryPublishingImpl$AgpDecorated. at org.gradle.internal.metaobject.AbstractDynamicObject$CustomMissingMethodExecutionFailed.<init>(AbstractDynamicObject.java:190) at org.gradle.internal.metaobject.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:184) at org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:84) at build_cbf15uup5mups67kcekw2jm8o$_run_closure1$_closure10.doCall$original(D:\Users\XIAO KA\AndroidStudioProjects\ocr03\tess-two\build.gradle:26) at build_cbf15uup5mups67kcekw2jm8o$_run_closure1$_closure10.doCall(D:\Users\XIAO KA\AndroidStudioProjects\ocr03\tess-two\build.gradle) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) at org.gradle.util.internal.ClosureBackedAction.execute(ClosureBackedAction.java:73) at org.gradle.util.internal.ConfigureUtil.configureTarget(ConfigureUtil.java:166) at org.gradle.util.internal.ConfigureUtil.configure(ConfigureUtil.java:107) at org.gradle.util.internal.ConfigureUtil$WrappedConfigureAction.execute(ConfigureUtil.java:178) at com.android.build.gradle.internal.dsl.LibraryExtensionImpl$AgpDecorated.publishing(Unknown Source) at com.android.build.gradle.LibraryExtension.publishing(LibraryExtension.kt) at com.android.build.gradle.LibraryExtension_Decorated.publishing(Unknown Source) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) at org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:547) at org.gradle.internal.metaobject.BeanDynamicObject.tryInvokeMethod(BeanDynamicObject.java:218) at org.gradle.internal.metaobject.CompositeDynamicObject.tryInvokeMethod(CompositeDynamicObject.java:99) at org.gradle.internal.extensibility.MixInClosurePropertiesAsMethodsDynamicObject.tryInvokeMethod(MixInClosurePropertiesAsMethodsDynamicObject.java:38) at org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:65) at build_cbf15uup5mups67kcekw2jm8o$_run_closure1.doCall$original(D:\Users\XIAO KA\AndroidStudioProjects\ocr03\tess-two\build.gradle:25) at build_cbf15uup5mups67kcekw2jm8o$_run_closure1.doCall(D:\Users\XIAO KA\AndroidStudioProjects\ocr03\tess-two\build.gradle) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) at org.gradle.util.internal.ClosureBackedAction.execute(ClosureBackedAction.java:73) at org.gradle.util.internal.ConfigureUtil.configureTarget(ConfigureUtil.java:166) at org.gradle.util.internal.ConfigureUtil.configure(ConfigureUtil.java:107) at org.gradle.util.internal.ConfigureUtil$WrappedConfigureAction.execute(ConfigureUtil.java:178) at org.gradle.internal.extensibility.ExtensionsStorage$ExtensionHolder.configure(ExtensionsStorage.java:177) at org.gradle.internal.extensibility.ExtensionsStorage.configureExtension(ExtensionsStorage.java:64) at org.gradle.internal.extensibility.DefaultConvention.configureExtension(DefaultConvention.java:388) at org.gradle.internal.extensibility.DefaultConvention.access$500(DefaultConvention.java:49) at org.gradle.internal.extensibility.DefaultConvention$ExtensionsDynamicObject.tryInvokeMethod(DefaultConvention.java:317) at org.gradle.internal.metaobject.CompositeDynamicObject.tryInvokeMethod(CompositeDynamicObject.java:99) at org.gradle.internal.extensibility.MixInClosurePropertiesAsMethodsDynamicObject.tryInvokeMethod(MixInClosurePropertiesAsMethodsDynamicObject.java:38) at org.gradle.groovy.scripts.BasicScript$ScriptDynamicObject.tryInvokeMethod(BasicScript.java:138) at org.gradle.internal.metaobject.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:163) at org.gradle.api.internal.project.DefaultDynamicLookupRoutine.invokeMethod(DefaultDynamicLookupRoutine.java:58) at org.gradle.groovy.scripts.BasicScript.invokeMethod(BasicScript.java:87) at build_cbf15uup5mups67kcekw2jm8o.run(D:\Users\XIAO KA\AndroidStudioProjects\ocr03\tess-two\build.gradle:15) at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91) ... 184 more
最新发布
05-14
<think>好的,用户遇到了Gradle构建错误,具体是“Could not find method publications()”在使用Tess-Two库的Android项目中。我需要结合用户之前的问题和提供的引用来分析解决。 首先,用户之前的问题涉及类加载错误,当时建议升级插件和清理缓存。现在的新错误可能与Gradle版本升级后的API变更有关。根据引用[4],Gradle 7.1之后,某些方法可能被废弃或修改,比如publications()的使用方式。需要确认用户是否正确配置了发布相关的插件和DSL。 用户现在的问题是关于publications()方法找不到,这可能是因为在模块级别的build.gradle中没有正确应用maven-publish插件,或者在配置publications时使用了旧语法。例如,可能是在没有应用插件的情况下直接调用了publications块,或者DSL结构不符合新版本的要求。 另外,用户的项目中可能同时存在多个Maven插件,如旧的android-maven和新版maven-publish,导致冲突。需要检查是否移除了旧插件,如com.github.dcendents.android-maven,并替换为正确的插件。 根据之前的解决方案,用户应该使用maven-publish插件,并按照新的DSL配置。需要确认publications块是否正确嵌套在publishing块内,以及是否在适当的位置应用了插件。同时,Gradle版本是否升级到兼容的版本,如8.x,因为旧版本的Gradle可能不支持新的语法。 此外,用户可能没有正确配置组件,比如在afterEvaluate中引用release组件,这在新版AGP中可能需要不同的处理方式。需要检查是否在模块中正确设置了组件发布,并确保使用了正确的依赖配置。 可能还需要检查Gradle的缓存问题,如果之前的缓存未清理干净,可能会导致新旧配置冲突。建议用户执行清理缓存和重新同步项目的步骤,如删除~/.gradle/caches/目录,并使用--refresh-dependencies重新获取依赖。 最后,需要确保所有配置符合Android Gradle Plugin 8.1.0的要求,因为旧版的Tess-Two库可能需要进行适配,或者需要调整发布配置以匹配新的API。可能需要参考官方文档,更新publications的配置方式,使用新的DSL元素,如components.release替代旧的artifacts方式。</think>根据Gradle 8.1+和AGP 8.1.0的API变更,结合Tess-Two库的本地发布需求,以下是系统性解决方案: --- ### 一、错误根源定位 `Could not find method publications()`错误主要由以下原因导致: 1. **插件未正确应用**:未声明`maven-publish`插件或应用顺序错误[^4] 2. **DSL层级错位**:`publications`配置块未嵌套在`publishing`块内[^4] 3. **组件未注册**:Android库未暴露`release`组件给发布系统[^4] --- ### 、分步修复方案 #### ▶ 步骤1:统一插件配置 ```groovy // 模块级build.gradle (libraries/tess-two) plugins { id 'com.android.library' id 'maven-publish' // 必须声明在plugins块内[^4] } // 移除旧版插件 // apply plugin: 'com.github.dcendents.android-maven' // 冲突根源[^1] ``` #### ▶ 步骤2:规范发布配置结构 ```groovy // 确保层级关系正确 publishing { publications { mavenAar(MavenPublication) { // 自定义发布任务名称 groupId = 'com.github.tesseract-ocr' artifactId = 'tess-two' version = '4.1-local' // 必须使用afterEvaluate等待组件初始化[^4] afterEvaluate { from components.release } } } repositories { maven { url = uri("${rootProject.projectDir}/libraries") // 本地仓库需配置metadataSources[^4] metadataSources { mavenPom() artifact() } } } } ``` #### ▶ 步骤3:组件可见性控制 ```groovy android { publishing { singleVariant('release') { withSourcesJar() // 包含源码包 withJavadocJar() // 包含文档包 } } } ``` --- ### 三、兼容性验证 | 配置项 | 要求 | 验证命令 | 修复效果 | |--------|------|----------|----------| | `maven-publish`插件版本 | 内置 | `./gradlew buildEnvironment` | 消除方法缺失错误 | | Gradle Wrapper版本 | ≥8.1.1 | `./gradlew --version` | 支持新DSL语法 | | 组件可见性 | 显式声明release | `./gradlew tasks --all` | 显示publishing任务 | --- ### 四、故障树分析(FTA) ```mermaid graph TD A[Could not find method publications] --> B{原因分类} B --> C[插件缺失] B --> D[DSL结构错误] B --> E[组件不可见] C --> C1[未应用maven-publish插件] C --> C2[插件应用顺序错误] D --> D1[publications不在publishing块内] D --> D2[未使用afterEvaluate] E --> E1[未声明singleVariant] E --> E2[AGP版本低于8.1.0] ``` --- ### 五、替代方案(若仍失败) 1. **降级兼容模式**(临时方案): ```groovy // gradle.properties android.useNewApkPublisher=false // 关闭新发布系统 ``` 2. **动态组件选择**: ```groovy afterEvaluate { publishing { publications { mavenAar(MavenPublication) { // 自动选择最新构建变体 def variant = android.libraryVariants.find { it.buildType.name == 'release' } from variant.javaCompileProvider.get().destinationDirectory } } } } ``` --- ### 六、调试命令推荐 ```shell # 检查发布任务结构 ./gradlew :libraries:tess-two:tasks --all | grep publish # 强制刷新依赖 ./gradlew --refresh-dependencies clean publishToMavenLocal # 查看详细DSL结构 ./gradlew :libraries:tess-two:properties | grep publishing ``` --- ### 七、版本对照表 | 组件 | 错误版本 | 修复版本 | 变更点 | |------|----------|----------|--------| | Gradle | ≤7.0 | ≥8.1 | 引入新发布DSL[^4] | | AGP | ≤7.4 | ≥8.1 | 组件可见性控制 | | maven-publish | N/A | 内置 | 替代第三方插件 | [^1]: 旧版android-maven插件与Gradle 8+存在API冲突 [^4]: Android官方文档明确要求使用新发布系统
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值