Android組件化實戰之利用Maven優雅地調試SDK

打包sdk到Maven倉庫

Maven 是 Apache 下的一個純 Java 開發的開源項目,基於項目對象模型(縮寫:POM)概念,Maven能夠從中央信息管理一個項目的構建、報告和文檔等步驟。Maven 也可被用於構建和管理各類項目,例如 C#,Ruby,Scala 和其餘語言編寫的項目。html

POM介紹

POM(Project Object Model)即項目對象模型,經過xml格式保存的pom.xml文件,做用相似ant的build.xml文件,功能更強大。該文件用於管理:源代碼、配置文件、開發者的信息和角色、問題追蹤系統、組織信息、項目受權、項目的url、項目的依賴關係等等;node

Glide:POM舉個栗子android

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>com.github.bumptech.glide</groupId>  
  <artifactId>glide</artifactId>  
  <version>4.12.0</version>  
  <packaging>aar</packaging>  
  <name>Glide</name>  
  <description>A fast and efficient image loading library for Android focused on smooth scrolling.</description>  
  <url>https://github.com/bumptech/glide</url>  
  ...
</project>
複製代碼

POM節點

  • groupId : 組織標識,例如:com.github.bumptech.glide,在目錄下,將是: com/github/bumptech/glide目錄。
  • artifactId : 項目名稱,例如:Glide。
  • version : 版本號。
  • packaging : 打包的格式,能夠爲:pom , jar , maven-plugin , ejb , war , ear , rar , par ,aar等。

Maven的目標

  • 簡化構建過程
  • 提供統一的構建系統
  • 提供優質的項目信息
  • 鼓勵更好的開發實踐

Maven倉庫

Maven 倉庫能幫助咱們管理構件(主要是JAR),它就是放置全部JAR文件(WAR,ZIP,POM,AAR等等)的地方。git

舉個栗子:阿里&jcenter& maven 倉庫github

Android引入倉庫 : 根 build.gradle配置 gradle—docapache

  1. buildscript repositories vs 2.allprojects repositories
buildscript {
   repositories {
       		jcenter()
          google()
      }
    }
allprojects {
    addRepos(repositories)
    repositories{
    	 jcenter()
       google()
       mavenLocal()
     	 mavenCentral()
       maven { url "http://maven.aliyun.com/nexus/content/groups/public" }
       maven { url "file:///${rootProject.getRootDir()}/asdk" }
       maven { url "file:///${rootProject.getRootDir()}/bsdk" }
    }
}
複製代碼

buildscript { }:Configures the build script classpath for this project.vim

allprojects { }:Configures this project and each of its sub-projects.api

註解:buildscript是gradle腳本執行所需依賴,allprojects是項目自己須要的依賴,因此咱們將本身所須要的倉庫加到allprojects配置中安全

經過以上咱們知道,打包sdk 須要一個託管的倉庫,那麼下面咱們就介紹一下,如何搭建一個私有倉庫;基於安全考慮不用公共倉庫,學習一下如何搭建私有倉庫。bash

經過nexus搭建私有倉庫

Nexus 簡介:是Maven倉庫管理器,若是你使用Maven,你能夠從Maven中央倉庫 下載所須要的構件(artifact)

簡介2:World’s #1 Repository Manager(本身誇本身世界第一,其餘吹牛逼的不用看了)Single source of truth for all of your components, binaries, and build artifacts Efficiently distribute parts and containers to developers Deployed at more than 100,000 organizations globally

搭建Maven私有倉庫步驟

1.下載

www.sonatype.com/download-os…

2.啓動

~ » /Users/caining/Documents/applications/nexus-3.28.1-01-mac/nexus-3.28.1-01/bin/nexus start
Starting nexus
複製代碼

3.訪問

http://localhost:8081/

4.修改端口方法

cd /Users/caining/Documents/applications/nexus-3.28.1-01-mac/nexus-3.28.1-01/etc
vim nexus-default.properties

###########################配置以下

# Jetty section
application-port=8081
application-host=0.0.0.0
複製代碼
image-20210326202528170

5.登陸

nexus 2 的默認帳號密碼 admin:默認密碼admin123登陸; nexus 3第一次啓動後 nexus3 會自動生成admin 的密碼,存在admin.password

image-20210326205307574
查看密碼
~ » vim /Users/caining/Documents/applications/nexus-3.28.1-01-mac/sonatype-work/nexus3/admin.password
複製代碼

3866aa0a-39e2-4e14-90bb-4a31c6c303e1

image-20210326210024703

6.首次登陸後設置密碼

7.中止

~ » /Users/caining/Documents/applications/nexus-3.28.1-01-mac/nexus-3.28.1-01/bin/nexus stop
Shutting down nexus
Stopped.
複製代碼

gradle 腳本打包sdk並上傳Maven repository

1、在工程下新建 maven-push.gradle 腳本

apply plugin: 'maven'

uploadArchives {
      repository(url: maven.address) { authentication(userName: maven.username, password: maven.password) }
      pom.groupId = maven.MAVENGROUPID
      pom.artifactId = ARTIFACT
      pom.version = maven.appLibVersion
      pom.packaging = 'aar'
      pom.project {
                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
            }
}
複製代碼

2、配置根gralde配置

1.新建 config.gradle
2.apply from: 'config.gradle'
3.
ext {
		  maven = [
            address : "http://localhost:8081/repository/maven-releases/",//maven 倉庫地址
            username : "admin",
            password : "123456",
            appLibVersion : "1.0.6",//打包版本號
            buildMAVEN : true ,//是否打開upload功能,爲宿主工程準備、、最小侵入宿主工程
            MAVENGROUPID : "com.cnn.sdk"//打包groupId 這裏統一設置,如須要不一樣,請module中單獨設置
    ]
}
複製代碼

三 、gradle ext 是什麼?

  1. ext屬性是ExtensionAware類型的一個特殊的屬性,本質是一個Map類型的變量;
  2. 使用ext屬性的好處能夠在任何能獲取到rootProject的地方訪問這些屬性
  3. gradle.properties 與 ext 的不一樣?因爲ext 結構是map,因此能夠分組,比 gradle.properties 好用一些,一些系統級的配置能夠放gradle.properties ,用戶基本的配置能夠放ext 好比版本號啥的。

4、module 子 gradle.properties 增長artifact名字

  1. 新建module gradle.properties
  2. ARTIFACT= artifact—name // 這個不能隨意起,起名規則後面講

5、sdk-module 子 build.gradle 增長配置

try {
    if (maven.buildMAVEN){//這裏是true 在宿主工程裏,會訪問不到而報錯
        apply from: '../maven-push.gradle'
    }
}catch (all){
}
複製代碼

以上,執行 uploadArchives task 就會打包並upload 到倉庫

> Task :module01:uploadArchives
> Task :module02:writeReleaseAarMetadata
> Task :module02:bundleReleaseAar
> Task :module02:uploadArchives

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 781ms
43 actionable tasks: 41 executed, 2 up-to-date
10:46:48 AM: Task execution finished 'uploadArchives'.
複製代碼
image-20210330105751560

Module01 添加依賴implementation project(path: ':module02'),這時候再執行uploadArchives。

重點:拋出問題:若是模塊間依賴,以上腳本在全量打包時會報錯 以下

image-20210330123054236

緣由:module01 依賴是本地包,因此報錯

image-20210330134953074

如何解決?

  1. 思路1:先傳module02 再修改module01依賴爲線上包,再傳module01 ,這個思路可行,但若是遇到module 過多,執行起來過於麻煩,這裏再也不演示,感興趣的同窗可本身執行。

相互依賴打包優化

  1. 問題 :填坑對於有互相依賴的包如何處理?對於關聯依賴 sdk 如何一鍵 build 並上傳Maven倉庫

  2. 以上存在的問題 :以上腳本雖然初步完成了sdk 打包並上傳Maven倉庫,但有問題存在,加入sdk 子module 關聯依賴時,子包不發佈,主包沒法打包成功,那麼除了手動一步一步上傳外,有沒有辦法一鍵上傳?

  3. 優化思路:動態替換打包後groupId 和 version(因爲是動態替換,這裏的工程moudle 的名稱應該與gradle.properties配置的artifact 保持一致)

  4. 關鍵腳本以下:

pom.withXml {
                def childs = asNode().children()
                childs.each {
                    child ->
                        print("childName->"+child.name().toString()+"\n")
                        if (child.name().toString().contains('dependencies')) {
                            child.children().each {
                                print("dependencies->"+it.text().toString()+"\n")
                                if (it.text().toString().contains("unspecified")) {
                                    def iterator = it.children().iterator()
                                    def remove = false
                                    while (iterator.hasNext()) {
                                        def node = iterator.next()
                                        if (node.name().toString().contains('groupId')) {
                                            iterator.remove()
                                        }
                                        if (node.name().toString().contains('version')) {
                                            iterator.remove()
                                            remove = true
                                        }
                                    }
                                    if (remove) {
                                        it.appendNode('version', maven.appLibVersion)
                                        it.appendNode('groupId', maven.MAVENGROUPID)
                                    }
                                    print("\n return ->"+it.text().toString()+"\n")
                                }
                            }

                        }
                }
            }
複製代碼

宿主經過倉庫引入sdk

引入方式也很簡單

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "groupId:artifactId:version"//此處對應上傳的maven 倉庫的信息
}
複製代碼

經過宿主工程優雅的調試sdk

經過倉庫引入的第三方sdk 在宿主工程裏調試,很不方便,雖然能夠斷電,但源碼沒法修改,使得在宿主程序中,遇到問題,查問題時,很是不方便,那麼有沒有好的辦法,在本地開發時,不使用倉庫包,而是直接引用源碼呢?上線時,經過修改配置,引用遠程倉庫。

經過gradle腳本控制引用源碼or倉庫

咱們知道android module引入模塊,是在settings.gradle中,以下:

Module常規引入

include ':sdka'
複製代碼

參數控制動態引入

image-20210401135541636

  1. 宿主根gradle.properties 增長控制參數boolean useLocalLib = true/false

  2. 經過settings.gradle配置動態控制是否使用倉庫

if (useLocalLib.toBoolean()){
    print("sdk調試使用,線上環境忽略如下內容")
    include(':module01')
    include(':module02')
    print("path---->"+getRootDir().getParent())
    project(':module01').projectDir = new File(getRootDir().getParent(),"/MavenPackage/module01")
    project(':module02').projectDir = new File(getRootDir().getParent(),"/MavenPackage/module02")
}
複製代碼
  1. 同理,宿主工程引入lib時 ,用gradle.properties-useLocalLib字段控制引用倉庫or本地module
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    if (useLocalLib.toBoolean())
    	implementation project(":module01")
    else
    	implementation 'com.cnn.sdk:module01:1.0.0'
}
複製代碼

以上,能夠在宿主工程裏,經過參數userLocalSDK,達到引入sdk源碼的目的,源碼並不在宿主git 下;完成優雅的調試sdk 的目的。

總結

  • 經過Maven倉庫引入的好處:組件隔離,業務隔離,減小侵入等

  • 使用Nexus搭建Maven 私有倉庫,以及經常使用命令 初始密碼等,以及使用

  • 經過gradle plugin: 'maven' 打包並upload to Maven Repository

  • 宿主工程引用時,動態控制指向,是否打開源碼,達到調試sdk源碼的目的,而且git分

相關文章
相關標籤/搜索