安卓插件及发布jenter

疫情刚好静下心来回归过去的工作,工作以后往往都是往前跑,其实偶尔多回归下技术,沉淀下来,这是博主一直想做的插件和发布,以前总是各种事情耽搁,本章源码link,麻烦多多关注点星。

1.创建项目

   先创建一个基本项目,此处注意请尽量空白项目,避免乱七八糟报错。

在这里插入图片描述

2.创建插件库

2.1 删除所有java代码和res资源

2.2 创建groovy以及代码编写

2.3 创建meta-inf

在这里插入图片描述

2.4 build.gradle 讲解

//发布bintray的插件
apply plugin: 'com.novoda.bintray-release'
//groovy编译插件
apply plugin: 'groovy'

dependencies {
    compile "com.android.tools.build:gradle:3.4.1"
    compile group: 'org.javassist', name: 'javassist', version: '3.20.0-GA'
    //gradle sdk 依懒sdk
    compile gradleApi()
    //groovy sdk 依懒sdk
    compile localGroovy()
}

/**
 * 发布到bintray的配置
 */
publish {
    userOrg = 'applehusp' //此处一定要有,不然会报错
    repoName='com.model.buildgradle'   //对应仓库名
    groupId = 'com.model.buildgradle'  //对应仓库名
    artifactId = 'model-plugin'    //仓库的包名
    publishVersion = '1.0.0'       //包对应的版本名
    desc = 'this is a frame for android base'
    website = 'https://github.com/apple317/ModelPlugin.git'   //此处对应代码仓库地址
}

2.4 插件代码讲解

首先groovy脚本很想java,如果你有java功底,可以直接上手编写。

class ModelPlugin implements Plugin<Project> {

    //默认是app,直接运行assembleRelease的时候,等同于运行app:assembleRelease
    String compilemodule = "app"

    void apply(Project project) {
        String taskNames = project.gradle.startParameter.taskNames.toString()
        System.out.println("taskNames is " + taskNames)
        String module = project.path.replace(":", "")
        System.out.println("current module is " + module)
        AssembleTask assembleTask = getTaskInfo(project.gradle.startParameter.taskNames)
        if (assembleTask.isAssemble) {
            fetchMainModulename(project, assembleTask)
            System.out.println("compilemodule  is " + compilemodule)
        }

        if (!project.hasProperty("RunAlone")) {
            throw new RuntimeException("you should set isRunAlone in " + module + "'s gradle.properties")
        }

        //对于isRunAlone==true的情况需要根据实际情况修改其值,
        // 但如果是false,则不用修改
        boolean isRunAlone = Boolean.parseBoolean((project.properties.get("RunAlone")))
        String mainmodulename = project.rootProject.property("mainmodulename")
        if (isRunAlone && assembleTask.isAssemble) {
            //对于要编译的组件和主项目,isRunAlone修改为true,其他组件都强制修改为false
            //这就意味着组件不能引用主项目,这在层级结构里面也是这么规定的
            if (module.equals(compilemodule) || module.equals(mainmodulename)) {
                isRunAlone = true
            } else {
                isRunAlone = false
            }
        }
        project.setProperty("RunAlone", isRunAlone)

        //根据配置添加各种组件依赖,并且自动化生成组件加载代码
        if (isRunAlone) {
            project.apply plugin: 'com.android.application'
            if (!module.equals(mainmodulename)) {
                project.android.sourceSets {
                    main {
                        manifest.srcFile 'src/main/independent/AndroidManifest.xml'
                        java.srcDirs = ['src/main/java', 'src/main/independent/java']
                        res.srcDirs = ['src/main/res', 'src/main/independent/res']
                    }
                }
            }
            System.out.println("apply plugin is " + 'com.android.application')
            if (assembleTask.isAssemble) {
                if(module.equals(mainmodulename)){
                    compileAppComponents(assembleTask, project)
                }else{
                    compileComponents(assembleTask, project)
                }
            }
        } else {
            project.apply plugin: 'com.android.library'
            if (!module.equals(mainmodulename)) {
                project.android.sourceSets {
                    main {
                        manifest.srcFile 'src/main/AndroidManifest.xml'
                        java {
                            exclude 'src/main/independent/**'
                            exclude '**/independent/**.java'
                            exclude 'src/main/independent/**/res/layout/activity_independent.xml'
                        }
                    }
                }
            }
            System.out.println("apply plugin is " + 'com.android.library')
        }

    }

    /**
     * 根据当前的task,获取要运行的组件,规则如下:
     * assembleRelease ---app
     * app:assembleRelease :app:assembleRelease ---app
     * sharecomponent:assembleRelease :sharecomponent:assembleRelease ---sharecomponent
     * @param assembleTask
     */
    private void fetchMainModulename(Project project, AssembleTask assembleTask) {
        if (!project.rootProject.hasProperty("mainmodulename")) {
            throw new RuntimeException("you should set compilemodule in rootproject's gradle.properties")
        }
        if (assembleTask.modules.size() > 0 && assembleTask.modules.get(0) != null
                && assembleTask.modules.get(0).trim().length() > 0
                && !assembleTask.modules.get(0).equals("all")) {
            compilemodule = assembleTask.modules.get(0)
        } else {
            compilemodule = project.rootProject.property("mainmodulename")
        }
        if (compilemodule == null || compilemodule.trim().length() <= 0) {
            compilemodule = "app"
        }
    }

    private AssembleTask getTaskInfo(List<String> taskNames) {
        AssembleTask assembleTask = new AssembleTask()
        for (String task : taskNames) {
            if (task.toUpperCase().contains("ASSEMBLE")
                    || task.contains("aR")
                    || task.toUpperCase().contains("TINKER")
                    || task.toUpperCase().contains("INSTALL")
                    || task.toUpperCase().contains("RESGUARD")) {
                if (task.toUpperCase().contains("DEBUG")) {
                    assembleTask.isDebug = true
                }
                assembleTask.isAssemble = true
                String[] strs = task.split(":")
                assembleTask.modules.add(strs.length > 1 ? strs[strs.length - 2] : "all")
                break
            }
        }
        return assembleTask
    }

    /**
     * 自动添加依赖,只在运行assemble任务的才会添加依赖,因此在开发期间组件之间是完全感知不到的,这是做到完全隔离的关键
     * 支持两种语法:module或者groupId:artifactId:version(@aar),前者之间引用module工程,后者使用maven中已经发布的aar
     * @param assembleTask
     * @param project
     */
    private void compileAppComponents(AssembleTask assembleTask, Project project) {
        HashMap<String, Project> projectMash = project.rootProject.getChildProjects();
        String mainmodulename  = project.rootProject.property("mainmodulename")
        System.out.println("project mainmodulename== " + mainmodulename)
        ArrayList<Project> taskList = new ArrayList<>();
        for (String key : projectMash.keySet()) {
            System.out.println("project key== " + key)
            if (!key.equals(mainmodulename)
                    && projectMash.get(key).properties.get("RunAlone") != null) {
                System.out.println("project mainmodulename== " + mainmodulename)
                taskList.add(projectMash.get(key));
            }
        }
        System.out.println("project taskList== " + taskList.size())
        for (Project taskPro : taskList) {
            System.out.println("project taskList== " + taskPro.name)
            project.dependencies.add("api", project.project(':' + taskPro.name))
        }
    }

    private void compileComponents(AssembleTask assembleTask, Project project) {
        String components = (String) project.properties.get("component")
        if (components == null || components.length() == 0) {
            System.out.println("there is no add dependencies ")
            return
        }
        String[] compileComponents = components.split(",")
        if (compileComponents == null || compileComponents.length == 0) {
            System.out.println("there is no add dependencies ")
            return
        }
        for (String str : compileComponents) {
            System.out.println("comp is " + str)
            if (str.contains(":")) {
                /**
                 * 示例语法:groupId:artifactId:version(@aar)
                 * compileComponent=com.luojilab.reader:readercomponent:1.0.0
                 * 注意,前提是已经将组件aar文件发布到maven上,并配置了相应的repositories
                 */
                project.dependencies.add("api", str)
                System.out.println("add dependencies lib  : " + str)
            } else {
                /**
                 * 示例语法:module
                 * compileComponent=readercomponent,sharecomponent
                 */
                project.dependencies.add("api", project.project(':' + str))
                System.out.println("add dependencies project : " + str)
            }
        }
    }
    private class AssembleTask {
        boolean isAssemble = false
        boolean isDebug = false
        List<String> modules = new ArrayList<>()
    }
}

2.5 调试及输出

  博客地址https://blog.csdn.net/Apple_hsp/article/details/105184617,这个项目地址在https://gitee.com/applehsp/AndroidHspDemo中model分支。

在这里插入图片描述

3.发布jenter

3.1创建账户

在这里插入图片描述
在这里插入图片描述

3.2创建组织

在这里插入图片描述

3.3创建项目

在这里插入图片描述

3.3创建对应包

在这里插入图片描述

3.4 同步仓库代码

/**
 * 发布到bintray的配置
 */
publish {
    userOrg = 'applehusp' //此处一定要有,不然会报错
    repoName='com.model.buildgradle'   //对应仓库名
    groupId = 'com.model.buildgradle'  //对应仓库名
    artifactId = 'model-plugin'    //仓库的包名
    publishVersion = '1.0.0'       //包对应的版本名
    desc = 'this is a frame for android base'
    website = 'https://github.com/apple317/ModelPlugin.git'   //此处对应代码仓库地址
}

3.5 发布jenter

在这里插入图片描述
发布命令…/gradlew clean build bintrayUpload -PbintrayUser=账户名称 -PbintrayKey=apikey -PdryRun=false
在这里插入图片描述

3.6 遇到坑

vcs一定要填对,提示The version control 1.0.0 returns 404.
账户一定要选个人账户创建,公司不会出现add to jenter
一定要切老版样式。

在这里插入图片描述

4.jetbrains发布jenter

这是遇到的坑,上面插件会报一下错,然后使用这个插件脚本可以发布,参考github地址:https://github.com/apple317/AppleMvp
WARNING: API 'variant.getJavaCompiler()' 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.
To determine what is calling variant.getJavaCompiler(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.

4.1 类库下build.gradle 引用配置

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }

}

dependencies {
    api fileTree(dir: 'libs', include: ['*.jar'])
    api 'com.trello.rxlifecycle3:rxlifecycle:3.0.0'
    api 'androidx.multidex:multidex:2.0.0'
    api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.70"
    api 'com.trello.rxlifecycle3:rxlifecycle-components:3.0.0'
}

//以下是新增的,请直接copy
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'

//以下是需要针对项目需要修改的配置内容
//发布者的组织名称
group = "com.applehsp.mvp"
// 版本号,下次更新是只需要更改版本号即可
version = "1.0.0"
//上面配置后上传至bintray后的编译路径是这样的: compile 'com.clwater:bintraylibrary:0.0.1'

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
//读取 local.properties 文件里面的 bintray.user
def bintrayUser = properties.getProperty("bintray.user")
//读取 local.properties 文件里面的 bintray.apikey
def bintrayKey = properties.getProperty("bintray.apikey")

//项目主页
def siteUrl = 'https://github.com/apple317/AppleMvp.git'
//项目的版本控制地址
def gitUrl = 'https://github.com/apple317/AppleMvp.git'
//发布到JCenter上的项目名字,必须填写
def libName = "mvp-kotlin"
//文档连接
def javaDocLinks = "https://github.com/apple317/AppleMvp.git"
//Bintray中Repository的名字
def bintrayRepo = "com.applehsp.mvp"
//应用的描述
def bintrayDesc = "Desc"
//组织的名字, 建立组织账号后上传的时候需要这个, 个人张海时候不需要修改这部分
def bintrayUserOrg = "applehusp"

//生成源文件
task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}
//生成文档
task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    //以下两个为项目中带有中文注释的支持
    options.encoding "UTF-8"
    options.charSet 'UTF-8'
    options.author true
    options.version true
    options.links javaDocLinks
    failOnError false
}

//文档打包成jar
task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}
//拷贝javadoc文件
task copyDoc(type: Copy) {
    from "${buildDir}/docs/"
    into "docs"
}

//上传到jcenter所需要的源码文件
artifacts {
    archives javadocJar
    archives sourcesJar
}

// 配置maven库,生成POM.xml文件
install {
    repositories.mavenInstaller {
        // This generates POM.xml with proper parameters
        pom {
            project {
                packaging 'aar'
                //项目名称和描述
                name 'pom project name'
                description 'pom project escription'
                url siteUrl
                licenses {
                    license {
                        //开源协议,在bintray中创建仓库时选择的license为Apache-2.0,复制下面的就可以
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    //开发者的个人信息
                    developer {
                        id 'developer id '
                        name 'developer name '
                        email 'developer email'
                    }
                }
                scm {
                    connection gitUrl
                    developerConnection gitUrl
                    url siteUrl
                }
            }
        }
    }
}

//上传到jcenter
bintray {
    user = bintrayUser
    key = bintrayKey
    configurations = ['archives']
    pkg {
        userOrg = bintrayUserOrg
        repo = bintrayRepo
        name = libName
        desc = bintrayDesc
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        licenses = ["Apache-2.0"]
        publish = true
    }
}

4.2 工程build.gradle 引用配置

在这里插入图片描述

4.2 配置用户和apikey

在这里插入图片描述

4.3 发布

./gradlew install
./gradlew bintrayUpload


版权声明:本文为Apple_hsp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。