AS Arctic Fox configuration 360 reinforced command line mode gradle plug-in

Create self-defined plug-ins in gradle. Gradle provides three ways:
In build Used directly in gradle scripts
Use in buildSrc
Used in stand-alone modules
This article introduces the third method. The plug-in of the third method can be uploaded to the local or network for other projects or projects

1, Configuration process

1.1 coding of plug-in module

You can create a new module, java module or android library module. Anyway, the build of the plug-in module will be modified later Gradle file, remove relevant dependencies.
Create a new groovy directory under the main directory of the plug-in module, and use groovy syntax for function development under this directory.
Custom Task attribute extension class configbean groovy

//ConfigBean.groovy
package com.shan.plugin;

public class ConfigBean {
    private String userName;
    private String userPassword;
    private String keyStorePath;
    private String keyStorePassword;
    private String keyAlias;
    private String keyAliasPassword;
    private String jarToolsPath;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public String getKeyStorePath() {
        return keyStorePath;
    }

    public void setKeyStorePath(String keyStorePath) {
        this.keyStorePath = keyStorePath;
    }

    public String getKeyStorePassword() {
        return keyStorePassword;
    }

    public void setKeyStorePassword(String keyStorePassword) {
        this.keyStorePassword = keyStorePassword;
    }

    public String getKeyAlias() {
        return keyAlias;
    }

    public void setKeyAlias(String keyAlias) {
        this.keyAlias = keyAlias;
    }

    public String getKeyAliasPassword() {
        return keyAliasPassword;
    }

    public void setKeyAliasPassword(String keyAliasPassword) {
        this.keyAliasPassword = keyAliasPassword;
    }

    public String getJarToolsPath() {
        return jarToolsPath;
    }

    public void setJarToolsPath(String jarToolsPath) {
        this.jarToolsPath = jarToolsPath;
    }

    @Override
    public String toString() {
        return "ConfigBean{" +
                "userName='" + userName + '\'' +
                ", userPassword='" + userPassword + '\'' +
                ", keyStorePath='" + keyStorePath + '\'' +
                ", keyStorePassword='" + keyStorePassword + '\'' +
                ", keyAlias='" + keyAlias + '\'' +
                ", keyAliasPassword='" + keyAliasPassword + '\'' +
                ", jarToolsPath='" + jarToolsPath + '\'' +
                '}';
    }
}

Plug in class jiaguplugin groovy

//JiaguPlugin.groovy
package com.shan.plugin;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import com.android.build.gradle.AppExtension;
import com.android.build.gradle.api.ApplicationVariant;
import com.android.build.gradle.api.BaseVariantOutput;


/**
 * Author by wuyishan, Date on 2022/1/19.
 */
class JiaguPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {
        println 'JiaguPlugin start'
        println 'JiaguPlugin start1'
        final ConfigBean mConfigExtension = project.getExtensions().create("mConfigExtension",ConfigBean.class);
        println 'JiaguPlugin start2'
        project.afterEvaluate(new Action<Project>() {
            @Override
            void execute(Project project2) {
                println 'JiaguPlugin start3'
                AppExtension appExtension = project2.getExtensions().getByType(AppExtension.class);
                println 'JiaguPlugin start4'
                appExtension.getApplicationVariants().all(new Action<ApplicationVariant>(){
                    @Override
                    void execute(ApplicationVariant applicationVariant) {
                        println 'JiaguPlugin start5'
                        applicationVariant.getOutputs().all(new Action<BaseVariantOutput>() {
                            @Override
                            void execute(BaseVariantOutput baseVariantOutput) {
                                File outputFile = baseVariantOutput.getOutputFile();
                                println 'JiaguPlugin start6===='+outputFile.getName()
                                if (outputFile.getName().contains("release")) {
                                    project2.getTasks().create("jiagu",JiaguTask.class,outputFile,mConfigExtension);
                                }
                            }
                        });
                    }
                });
            }
        });
    }
}

Plug in task class 1jiagutask groovy

//JiaguTask.groovy
package com.shan.plugin;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecSpec;
import javax.inject.Inject;
/**
 * Author by wuyishan, Date on 2022/1/20.
 */
class JiaguTask extends DefaultTask {
    @Internal
    def mApk
    private final ConfigBean mConfigExtension
    @Internal
    def userName;
    @Internal
    def userPassword;
    @Internal
    def keyStorePath;
    @Internal
    def keyStorePassword;
    @Internal
    def keyAlias;
    @Internal
    def keyAliasPassword;
    @Internal
    def jarToolsPath;

    @Inject
    JiaguTask(File mApk, ConfigBean mConfigExtension) {
        setGroup("jiagu")
        println 'JiaguTask start,path:'+mApk.getAbsolutePath()
        println 'JiaguTask start,mConfigExtension:'+mConfigExtension.toString()
        this.mApk = mApk
        this.mConfigExtension = mConfigExtension
        userName = mConfigExtension.getUserName()
        userPassword = mConfigExtension.getUserPassword()
        keyStorePath = mConfigExtension.getKeyStorePath()
        keyStorePassword = mConfigExtension.getKeyStorePassword()
        keyAlias = mConfigExtension.getKeyAlias()
        keyAliasPassword = mConfigExtension.getKeyAliasPassword()
        jarToolsPath = mConfigExtension.getJarToolsPath()

    }

    @TaskAction
    void doAction() {
        // SystemOutPrint.println("JiaguTask is running ");
        println 'JiaguTask is running,mConfigExtension='+mConfigExtension.toString()
        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                //println 'JiaguTask is running, getProject().exe='+mConfigExtension.getJarToolsPath()
                execSpec.commandLine("java","-jar",jarToolsPath,"-login",userName,userPassword)
            }
        });

        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                execSpec.commandLine("java","-jar",jarToolsPath,"-importsign",keyStorePath,keyStorePassword,keyAlias, keyAliasPassword)
            }
        });

        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                println 'JiaguTask end,mApk path='+mApk.getAbsolutePath()
                println 'JiaguTask end,mApk Parent='+mApk.getParent()
                execSpec.commandLine("java","-jar",jarToolsPath,"-jiagu",mApk.getAbsolutePath(),mApk.getParent(),"-autosign");
            }
        });
    }
}

Plug in task class 2jiagutask Groovy (you can choose between 1 and 2, but the extended attributes are used in different ways)

package com.shan.plugin;

import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecSpec;

import java.io.File;

import javax.inject.Inject;

/**
 * Author by wuyishan, Date on 2022/1/20.
 */
class JiaguTask extends DefaultTask {
    def mApk
    private final ConfigBean mConfigExtension

    @Inject
    JiaguTask(File mApk, ConfigBean mConfigExtension) {
        setGroup("jiagu")
        println 'JiaguTask start,path:'+mApk.getAbsolutePath()
        println 'JiaguTask start,mConfigExtension:'+mConfigExtension.toString()
        this.mApk = mApk
        this.mConfigExtension = mConfigExtension
    }

    @TaskAction
    void doAction() {
        println 'JiaguTask is running,mConfigExtension='+mConfigExtension.toString()
        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                // execSpec.commandLine("java","-jar",jarToolsPath,"-login",userName,userPassword)
                execSpec.commandLine("java","-jar",project.extensions.mConfigExtension.jarToolsPath,"-login",project.extensions.mConfigExtension.userName,project.extensions.mConfigExtension.userPassword)
            }
        });

        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                execSpec.commandLine("java","-jar",project.extensions.mConfigExtension.jarToolsPath,"-importsign",project.extensions.mConfigExtension.keyStorePath,project.extensions.mConfigExtension.keyStorePassword,project.extensions.mConfigExtension.keyAlias, project.extensions.mConfigExtension.keyAliasPassword)
            }
        });

        getProject().exec(new Action<ExecSpec>() {
            @Override
            public void execute(ExecSpec execSpec) {
                println 'JiaguTask end,mApk path='+mApk.getAbsolutePath()
                println 'JiaguTask end,jarToolsPath='+project.extensions.mConfigExtension.jarToolsPath
                execSpec.commandLine("java","-jar",project.extensions.mConfigExtension.jarToolsPath,"-jiagu",mApk.getAbsolutePath(),mApk.getParent(),"-autosign");
            }
        });
    }
}


Create a new resources directory in the main directory of the plug-in module, a new META-INF directory in the resources directory, a new gradle plugins directory in the META-INF directory, and a new file com.com under the gradle plugins directory shan. plugin. Properties, com shan. Plugin is the package name, which is followed by build.exe of app module Gradle file via the apply plugin: 'com shan. Plugin 'to call the plug-in. com.shan.plugin. The properties content shows the package name and class name of the plug-in

implementation-class=com.shan.plugin.JiaguPlugin

1.3 plug-in build Gradle publishing configuration

//build.gradle
plugins {
    id 'groovy'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation gradleApi()
    //implementation 'com.android.tools.build:gradle:7.0.2'
    implementation 'com.android.tools.build:gradle:4.1.0'
}

apply plugin: 'maven-publish'

publishing{
    publications{
        JiaguPlugin(MavenPublication){
            from components.java
            groupId 'com.shan'
            artifactId "jiagu"
            version '1.0'
        }
    }
/*    repositories {
        maven {
            url "../repo"
        }
    }*/
}

After this configuration, the publishing directory can be displayed in the gradle task on the right side of android studio. We can pack and publish the plug-ins in the local warehouse C: \ users \ username M2 \ repository path. If you want to modify the save location, you can use Maven URL property settings.

1.4 root directory build Gradle configuration

After the plug-in is generated, it can be used. It is in the root directory of build In gradle, the plug-in and version are specified by groupId, artifactId and version

//build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        /*maven {
            url "/repo"
        }*/
        mavenLocal()
        mavenCentral()
        google()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.2"
        classpath "com.shan:jiagu:1.0"
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

1.5 build. In app module Gradle configuration

Build. In app module Gradle needs to configure some parameters required for 360 packaging, that is, configbean Some properties defined in groovy require values.

At this time, the jiagu group is displayed in the app gradle task on the right side of android studio. After compiling apk, the dual computer jiagu task can be completed, or the reinforcement of apk can be completed through gradlew jiagu command on the command line

2, Stepping pit

2.1.Could not resolve com.android.tools.build:gradle:7.0.2

Plugin module synchronization gradle error

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation gradleApi()
    //implementation 'com.android.tools.build:gradle:7.0.2'
    implementation 'com.android.tools.build:gradle:4.1.0'
}

Solution: use the old version of implementation 'com android. tools. build:gradle:4.1.0’

2.2.Build was configured to prefer settings repositories over project repositories but repository 'Gradle Libs' was added by unknown code

An error is reported when the plugin module synchronizes gradle
Solution: delete the root directory settings Repository iesmode. In gradle file Set (repositoriesmode. Fail_on_project_repos), which is automatically added by the new project of the latest as version

2.3. Do not display Gradle task



Solution: first remove "Do not build Gradle list during Gradle sync" from the empirical option in the setting, and then synchronize Gradle

2.4.app module cannot find a custom plug-in

After the user-defined plug-in is published to the local warehouse, it can be found in build.com in the root directory Gradle relies on the classpath "com.shan:jiagu:1.0", but in the build.0 of app module Gradle file via the apply plugin: 'com shan. Prompt that plugin 'cannot be found when it is referenced
Solution: you can refer to https://www.jianshu.com/p/cce4201a3a2c , it is because the resources directory of the plug-in module and the groovy directory are not in the same directory.

2.5.class com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated cannot be cast to class

com.android.build.api.variant.ApplicationVariant (com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated and com.android.build.api.variant.ApplicationVariant are in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader @736a0d51)

Solution: because gradle:7.0.2 does not support com android. build. gradle. api. Basevariantoutput class. The version is too high and not supported. Reduce the version

2.6. Cannot run program "E:\study\praticeItems\GradleApp\app\java\bin\keytool.exe": CreateProcess error=2, the system cannot find the specified file


Referring to the 360 reinforcement document, the command reinforcement mode needs to be executed in the specified java directory provided by it, because there is keytool exe,aapt.exe,aapt2.exe these tools

2.7. Cannot run program "E:\study\praticeItems\GradleApp\app\java\bin\aapt.exe": CreateProcess error=2, the system cannot find the specified file.

Cannot run program "E:\study\praticeItems\GradleApp\app\java\bin\aapt2.exe": CreateProcess error=2, the system cannot find the specified file.
Solution: the same as 6

Keywords: Java Apache Gradle Groovy

Added by mzm on Tue, 25 Jan 2022 09:39:48 +0200