为Android组件化项目搭建Maven私服

概览

文章目录

      • 概览
      • 前言
      • 搭建 maven 私服
        • 服务器环境
        • jdk安装配置
        • nexus安装配置
        • 管理创建存储点、仓库
      • 项目中使用 maven 私服
        • 上传 module 到仓库
          • 自动发布 module
          • 手动上传单个aar包
        • 引用仓库中的 module
          • build.gradle引入远程module
      • FAQ
        • 开发阶段有些module用远程依赖,有些module用本地依赖,造成BuildConfig中DEBUG环境变量不一致?
        • 发布的组件中远程依赖引用不到了?
        • 引用的第三方aar无需根据编译环境分别打包正式/测试版,如何处理?
      • 参考链接

前言

本文根据网络上的文章以及个人实践,综合整理而成。
做这件事的目的,是为了缩短APP的编译时间。
记得接手公司项目的时候,项目已经使用了当时流行的组件化方案,当时项目刚起步,组件不多,比较轻量化,编译一次正式版用时大概五分钟左右。这几年随着项目和技术的发展,组件化方案中间重构更换了一次,项目中的组件也发展到了二十多个,现在编译一次正式版,不算加固时间,用时十七分钟左右。
开发调试阶段目前也饱受困扰。由于所有组件都依赖base_lib,只要base中改了一个字符,debug调试编译时所有组件就会重新编译一遍,及其浪费时间。

搭建 maven 私服

要正常安装使用 maven 私服,需要几个前置条件,如果你的服务器都满足的话,可以跳过这几个配置:

  • 根据nexus需求,安装合适的 java 环境
  • 安装合适的 nexus 版本
  • 打开服务器8081端口,用以支持在浏览器访问nexus管理页面
服务器环境
jdk安装配置

Download jdk 11这里我下载的是Linux x64 Compressed Archive-jdk-11.0.22这个版本
在这里插入图片描述

  1. 使用sftp上传到服务器/opt/jdk目录
    在这里插入图片描述

  2. 解压到当前目录

    cd /opt/jdk
    tar -zxvf jdk-11.0.22_linux-x64_bin.tar.gz
    

    在这里插入图片描述

  3. 使用sftp修改环境配置文件:/etc/profile

    #jdk config(在文档结尾插入)
    export JAVA_HOME=/opt/jdk/jdk-11.0.22
    export PATH=$PATH:$JAVA_HOME/bin
    export CLASSPATH=.:$JAVA_HIOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    

    在这里插入图片描述

  4. 重启 /etc/profile 使之重新生效:

    source /etc/profile
    
  5. 验证 JDK 是否安装成功

    java --version
    

    在这里插入图片描述

nexus安装配置

Download Sonatype Nexus Repository根据安装的java版本选择对应的安装包,这里我下载的是/nexus-3.68.1-02-java11-unix这个版本,对应java11
在这里插入图片描述

  1. 使用sftp上传到服务器/opt/nexus目录

  2. 解压到当前目录

    cd /opt/nexus
    tar -zxvf nexus-3.68.1-02-java11-unix.tar.gz
    

    在这里插入图片描述

  3. 使用sftp编辑配置文件/opt/nexus/nexus-3.68.1-02/bin/nexus.rc

    run_as_user="root"
    

    在这里插入图片描述

  4. 查看并开放8081端口

    # 查看防火墙某个端口是否开放
    firewall-cmd --query-port=8081/tcp
    # 开放防火墙端口 8081
    firewall-cmd --add-port=8081/tcp --permanent
    # 重新加载防火墙规则
    firewall-cmd --reload
    # 再次查看防火墙某个端口是否开放
    firewall-cmd --query-port=8081/tcp
    

    在这里插入图片描述

  5. 进入bin目录启动nexus

    cd /opt/nexus/nexus-3.68.1-02/bin
    ./nexus start
    

    在这里插入图片描述

  6. 浏览器进入管理页面,http://[服务器ip]:8081
    在这里插入图片描述

  7. 登录账号,admin 的密码在/opt/nexus/sonatype-work/nexus3/admin.password文件中
    在这里插入图片描述

管理创建存储点、仓库
  1. 创建存储点
    默认存储点是default,你也可以直接用默认的,不创建新的
    登录账号,依次进入Setting->Repository->Blob Stores
    在这里插入图片描述

  2. 创建仓库
    在创建仓库前,先介绍一下仓库的三种存储类型Release、Snapshot和Mixed,创建仓库时会使用到
    Release(正式版): 正式版,适合项目稳定后正式发布使用,特性看下面的原理简介。
    Snapshot(快照版): 快照版,适合项目在开发调试中使用,特性看下面的原理简介。
    Mixed(混合版): 可包含release和snapshot版本

    ReleaseSnapshot的原理简介:
    它们的主要区别在于本地获取这些依赖的机制不同。

    • 对于Release版本的项目: 当项目中添加了一个正式版的version为x的依赖时,构建工具在构建项目时会从远程仓库中下载这个version为x的依赖到本地仓库缓存起来,下次再构建项目时,构建工具会从本地仓库中查找是否存在这个version为x的依赖,存在就不会在去远程仓库中拉取。这种特性会导致在团队开发中,如果你发布一个正式版的项目时,仍然使用的是同一个version,就可能出现其他使用这个version项目的成员根本接收不到项目的最新变更,这是糟糕的,为了生命安全,大家尽量不要这么做。所以,在每次发布正式版项目时,必须更新version。
    • 对于Snapshot版本的项目: 当项目中添加了一个快照版的version为x的依赖时,不管本地仓库中是否存在这个version为x的依赖,构建工具都会尝试从远程仓库中查看这个version为x的依赖是否最新。这样就能保证团队开发时,所有使用这个version为x的依赖的项目都能获取到依赖最新的变更,而且不用不停的迭代依赖的version。最后一还有一点,Snapshot版项目发布时的version一定要以-SNAPSHOT结尾,英文字母必须大写。

    依次进入Setting->Repository->Repositories
    在这里插入图片描述
    在这里插入图片描述

项目中使用 maven 私服

上传 module 到仓库
自动发布 module
  1. 在module的 build.gradle 同级创建publish.gradle

    apply plugin: "maven-publish"afterEvaluate {def ext = rootProject.extpublishing {publications {release(MavenPublication) {groupId 'com.wln100.future'artifactId 'fragmentation'version '1.0.0-SNAPSHOT'if (isAndroidEnv(project)) {from project.components.release} else {from project.components.java}pom {name = 'fragmentation'description = 'fragmentation'url = ext.nexusMavenUrl}}}repositories {maven {allowInsecureProtocol trueurl = ext.nexusMavenUrlcredentials {username ext.nexusMavenUsernamepassword ext.nexusMavenPassword}}}}
    }static def isAndroidEnv(Project project) {return project.getPlugins().hasPlugin('com.android.application') || project.getPlugins().hasPlugin('com.android.library')
    }
    
  2. 在 module 的 build.gradle 引入 publish.gradle

    apply plugin: 'com.android.library'...
    android {compileSdk compileVersiondefaultConfig {...}buildTypes {...}...}dependencies {...
    }
    //引入自动发布gradle
    apply from: project.file('publish.gradle')
    
  3. 同步代码,运行GradleTask
    在这里插入图片描述

  4. 之后在仓库管理页面可以看到上传成功的module
    在这里插入图片描述

手动上传单个aar包
  1. 管理页面进入Upload->android-examonline-hosted
    在这里插入图片描述

  2. 上传aar,填写必要参数
    在这里插入图片描述
    在这里插入图片描述

引用仓库中的 module

首先需要在项目级的build.gradle中添加仓库地址:

buildscript {...repositories {//本地私服仓maven {allowInsecureProtocol trueurl 'http://[服务器ip]:8081/repository/[仓库名称]/'}...}...
}
...
allprojects {repositories {//本地私服仓maven {allowInsecureProtocol trueurl 'http://[服务器ip]:8081/repository/[仓库名称]/'}...}
}
...
build.gradle引入远程module
dependencies {//引入组件module  api 'com.wln100.future:fragmentation:1.0.0-SNAPSHOT'//引入单个aarapi 'me.yokeyword.fragmentation:fragmentation_core:1.0'
}

FAQ

开发阶段有些module用远程依赖,有些module用本地依赖,造成BuildConfig中DEBUG环境变量不一致?

我的解决方式为,发布module时,分别发布debug和release两包到两个仓库中;引入依赖时,根据编译命令动态切换对应的私服仓库:

  1. 发布时分别发布debug和release
    //publish.gradle
    afterEvaluate {publishing {publications {release(MavenPublication) {...if (isAndroidEnv(project)) {//打包release modulefrom project.components.release} else {from project.components.java}...}debug(MavenPublication) {...if (isAndroidEnv(project)) {//打包debug modulefrom project.components.debug} else {from project.components.java}...}}repositories {maven {allowInsecureProtocol true//根据编译任务动态设置发布仓库if (isReleaseBuild()) {url = NEXUS_URL} else {url = NEXUS_DEBUG_URL}...}}}// 定义一个函数来判断是否为release版本
    def isReleaseBuild() {def taskNames = gradle.startParameter.taskNamesprintln "isReleaseBuild>>>>taskNames:$taskNames"return taskNames.any { it.toLowerCase().contains("release") }
    }
  2. 项目根目录build.gradle动态设置仓库
    //project build.gradle
    ...
    allprojects {apply from: "$rootDir/gradle/maven-utils.gradle"repositories {...//本地私服仓-自有组件maven {allowInsecureProtocol trueif (isReleaseBuild()) {url NEXUS_URL} else {url NEXUS_DEBUG_URL}}google()...maven { url 'https://jitpack.io' }}
    }
    
发布的组件中远程依赖引用不到了?

发布时配置发布参数withxml

afterEvaluate {publishing {publications {release(MavenPublication) {...pom {...withXml {def dependenciesNode = asNode().getAt('dependencies')[0] ?:asNode().appendNode('dependencies')configurations.api.getDependencies().each {dep -> addDependency(project, dependenciesNode, dep, "compile")}configurations.implementation.getDependencies().each {dep -> addDependency(project, dependenciesNode, dep, "runtime")}}}}debug(MavenPublication) {...pom {...withXml {def dependenciesNode = asNode().getAt('dependencies')[0] ?:asNode().appendNode('dependencies')configurations.api.getDependencies().each {dep -> addDependency(project, dependenciesNode, dep, "compile")}configurations.implementation.getDependencies().each {dep -> addDependency(project, dependenciesNode, dep, "runtime")}}}}}...}
}private void addDependency(Project project, def dependenciesNode, Dependency dep, String scope) {if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified") {return}if (dep.version == 'unspecified') {return}final dependencyNode = dependenciesNode.appendNode('dependency')dependencyNode.appendNode('scope', scope)dependencyNode.appendNode('groupId', dep.group)dependencyNode.appendNode('artifactId', dep.name)dependencyNode.appendNode('version', dep.version)println("publish -> library <${dep.group}:${dep.name}:${dep.version}>")if (!dep.transitive) {// In case of non transitive dependency,// all its dependencies should be force excluded from them POM filefinal exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')exclusionNode.appendNode('groupId', '*')exclusionNode.appendNode('artifactId', '*')} else if (!dep.properties.excludeRules.empty) {// For transitive with exclusions, all exclude rules should be added to the POM filefinal exclusions = dependencyNode.appendNode('exclusions')dep.properties.excludeRules.each { ExcludeRule rule ->final exclusionNode = exclusions.appendNode('exclusion')exclusionNode.appendNode('groupId', rule.group ?: '*')exclusionNode.appendNode('artifactId', rule.module ?: '*')}}
}
引用的第三方aar无需根据编译环境分别打包正式/测试版,如何处理?

新建一个专门存放三方aar库的私服仓库,单独上传依赖三方aar。

//project build.gradle
...
allprojects {apply from: "$rootDir/gradle/maven-utils.gradle"repositories {//本地私服仓-三方libmaven{allowInsecureProtocol trueurl 'http://x.x.x.x:8081/repository/android-third-lib-hosted/'}...google()...}
}

参考链接

Centos开放端口以及查看端口和防火墙配置命令
centos7下搭建nexus
CentOS 7 安装 JDK11(注意版本号要与自己的版本一致)
centos7安装Nexus(Maven私服)与配置使用教程
【github】Blankj/AndroidUtilCode-publish.gradle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/24291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20240607在ubuntu下解压缩7z的压缩包文件

20240607在ubuntu下解压缩7z的压缩包文件 2024/6/7 10:26 百度&#xff1a;ubuntu 7z解压缩 在Ubuntu中&#xff0c;可以使用7z命令来解压.7z文件。首先&#xff0c;确保你已经安装了p7zip-full包&#xff0c;如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo …

【雷达原理】一维CFAR检测算法——对比分析与代码实现

目录 引言一、仿真实例1.1 均匀背景杂波1.2 杂波边缘1.3 多干扰目标杂波 二、MATLAB代码参考文献 引言 推荐博文【目标检测】雷达目标CFAR检测算法 上述文章介绍了四种典型CFAR检测算法的特点及性能对比。本文将利用MATLAB进行仿真&#xff0c;通过实例验证和对比这几种算法的…

Linux 中常用的设置、工具和操作

1.设置固定的ip地址步骤 1.1 添加IPADDR“所设置的固定ip地址” TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"static" DEFROUTE"yes" IPV4_FAILURE_FATAL"no" IPV6INIT"yes" IPV6…

如何在virtualbox上安装Linux系统(centerOS)

提示&#xff1a;共同学习 注意&#xff1a;一定要在BIOS中的虚拟化打开。 文章目录 第一步&#xff1a; 第一步&#xff1a; 启动 、显示开启 centos基础安装 ​ ​

【MySQL | 第十二篇】重新认识MySQL数据类型

12.理解MySQL数据类型 12.1整数类型 整数类型有五种&#xff1a;tinyint、smallint、mediumint、int、bigint&#xff08;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;8字节&#xff09;&#xff0c;存储范围为 -2^(N-1) 到 2^(N-1)-1所有整数类型默认有符号数&…

关于RDMA传输的基本流量控制

Basic flow control for RDMA transfers | The Geek in the Corner (wordpress.com) 文心一言 已经介绍了使用发送/接收操作和RDMA读写操作&#xff0c;那么现在是一个很好的机会来结合这两种方法的元素&#xff0c;并讨论一般的流量控制。还会稍微谈谈RDMA带有立即数据的写操…

DeepDriving | 多目标跟踪算法之SORT

本文来源公众号“DeepDriving”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;多目标跟踪算法之SORT 1 简介 SORT是2016年发表的一篇文章《Simple Online and Realtime Tracking》中提出的一个经典的多目标跟踪算法&#xff0c;…

九大微服务监控工具详解

Prometheus Prometheus 是一个开源的系统监控、和报警工具包&#xff0c;Prometheus 被设计用来监控“微服务架构”。 主要解决&#xff1a; 监控和告警&#xff1a;Prometheus 可以对系统、和应用程序进行实时监控&#xff0c;并在出现问题时发送告警&#xff1b;数据收集和…

从0到1实现一个自己的大模型,实践中了解模型流程细节

前言 最近看了很多大模型&#xff0c;也使用了很多大模型。对于大模型理论似乎很了解&#xff0c;但是好像又缺点什么&#xff0c;思来想去决定自己动手实现一个 toy 级别的模型&#xff0c;在实践中加深对大语言模型的理解。 在这个系列的文章中&#xff0c;我将通过亲手实践…

问题:当频点数大于载波数时,() #学习方法#知识分享

问题&#xff1a;当频点数大于载波数时&#xff0c;&#xff08;&#xff09; A.基带跳频可以执行&#xff0c;混合跳频可以执行 B.基带跳频不可以执行&#xff0c;混合跳频可以执行 C.基带跳频可以执行&#xff0c;混合跳频不可以执行 D.基带跳频不可以执行&#xff0c;混…

用 Notepad++ 写 Java 程序

安装包 百度网盘 提取码&#xff1a;6666 安装步骤 双击安装包开始安装。 安装完成&#xff1a; 配置编码 用 NotePad 写 Java 程序时&#xff0c;需要设置编码。 在 设置&#xff0c;首选项&#xff0c;新建 中进行设置&#xff0c;可以对每一个新建的文件起作用。 Note…

IO进程线程(十)进程间通信 消息队列 共享内存 信号灯集

文章目录 一、IPC(Inter-Process Communication)进程间通信相关命令 &#xff1a;&#xff08;一&#xff09;ipcs --- 查看IPC对象&#xff08;二&#xff09;获取IPC键值&#xff08;三&#xff09;删除IPC对象的命令&#xff08;四&#xff09;获取IPC键值的函数1. 函数定义…

Maxkb玩转大语言模型

Maxkb玩转大语言模型 随着国外大语言模型llama3的发布&#xff0c;搭建本地个人免费“人工智能”变得越来越简单&#xff0c;今天博主分享使用Max搭建本地的个人聊天式对话及个人本地知识域的搭建。 1.安装Maxkb开源应用 github docker快速安装 docker run -d --namemaxkb -p 8…

FL Studio21.2.9中文破解版水果软件安装包附带激活码注册码

音乐制作软件&#xff0c;对很多人而言&#xff0c;是一个“高门槛”的存在。它既需要专业的音乐知识&#xff0c;也需要复杂的操作技巧。 「FL Studio 21中文版马丁版下载」&#xff0c;复制整段内容&#xff0c;打开最新版「夸克APP」即可获取链接&#xff1a; https://pan…

Dokcer 基础使用 (4) 网络管理

文章目录 Docker 网络管理需求Docker 网络架构认识Docker 常见网络类型1. bridge 网络2. host 网络3. container 网络4. none 网络5. overlay 网络 Docker 网路基础指令Docker 网络管理实操 其他相关链接 Docker 基础使用(0&#xff09;基础认识 Docker 基础使用(1&#xff09;…

git(其六)--总结

配置基础信息 //1.配置用户名和邮箱 git config --global user.name "带着引号写一个昵称" git config --global user.email "带着引号写一个邮箱"//2.建立一个git本地库 git init//3.查看本地内容 git status //可以看到那些处于待加入本地库的文件&a…

使用AutoGen框架进行多智能体协作:AI Agentic Design Patterns with AutoGen

AI Agentic Design Patterns with AutoGen 本文是学习https://www.deeplearning.ai/short-courses/ai-agentic-design-patterns-with-autogen/ 这门课的学习笔记。 What you’ll learn in this course In AI Agentic Design Patterns with AutoGen you’ll learn how to buil…

当C++的static遇上了继承

比如我们想要统计下当前类被实例化了多少次&#xff0c;我们通常会这么写 class A { public:A() { Count_; }~A() { Count_--; }int GetCount() { return Count_; }private:static int Count_; };class B { public:B() { Count_; }~B() { Count_--; }int GetCount() { return …

抢人!抢人!抢人! IT行业某岗位已经开始抢人了!

所谓抢滩鸿蒙&#xff0c;人才先行。鸿蒙系统火力全开后&#xff0c;抢人已成鸿蒙市场的主题词&#xff01; 智联招聘数据显示&#xff0c;春节后首周&#xff0c;鸿蒙相关职位数同比增长163%&#xff0c;是去年同期的2.6倍&#xff0c;2023年9-12月鸿蒙相关职位数同比增速为3…

前端开发常用的工具和软件,提高编程效率

目录 1. 文本编辑器与IDE (集成开发环境)2. 版本控制工具3. 构建工具与包管理器4. 前端框架与库5. 设计与原型工具6. 测试与调试工具7. 代码协作与项目管理8. 自动化部署与持续集成/持续部署(CI/CD)相关链接&#xff1a; 前端开发过程中使用的工具和软件种类繁多&#xff0c;可…