欢迎关注微信公众号:FSA全栈行动 👋
一、简述
目前(Android/java) library 的主要发布仓库有 MavenCentral 和 jitpack,我之前也对这两种仓库的发布流程做了详细介绍:
- 发布至 MavenCentral: juejin.cn/post/695359...
 - 发布至 jitpack: juejin.cn/post/704073...
 
但是,以上两种仓库,一般是用来免费发布开源 library 的,在提交库信息时,就会要求填写开源仓库的 url,如果我们不想开源源代码,仅仅只是希望把混淆后的 aar/jar 发布出去,那么上述两篇文章的流程就行不通了。
一般来说,这些平台也会提供付费服务,支持发布闭源的 library,就比如 jitpack 付费之后,才可以导入私有的 GitHub 仓库(即 private repo),从而构建并发布闭源的 library,可这笔费用不低的,具体费用见官网说明:
jitpack官网:jitpack.io/jitpack付费价格:jitpack.io/private#sub...
那有没有办法做到,既能免费又能闭源地发布 library 呢?Yes,这就是本篇要讲述的主要内容,灰常实用。
二、创建 library
温馨提示:这里只是举个简单的例子,熟悉 Android library 的朋友可以直接跳到下一节。
不管是 jar 还是 aar,对于 Android 开发者来说,都是 library,只是它们的 module 类型不同而已,简单来说,aar 是可以包含资源文件的 jar,功能更加强大,这里以 aar 为例,创建一个 android library module:
为了新手容易理解,这里有几点简单说明一下:
com.android.library:是 android library module 使用的 Gradle 插件,android {}是该插件的配置项,最终产出的库文件是*.aar。minifyEnabled:是否开启混淆,默认为 false。proguard-rules.pro:当前 library 编译时的混淆规则(minifyEnabled为true时生效),对生成最终的 aar 文件有影响。consumer-rules.pro:携带在 aar 文件中的混淆规则,对 别人工程 编译时的混淆规则有影响。
注:java library module 使用的 Gradle 插件是
java-library(apply plugin: 'java-library'),没有android{}配置项,如需混淆,则需要依赖其他 Gradle 插件,有需要的可以看我之前写的另一篇文章。Android - 混淆 java-library 工程:juejin.cn/post/717444...
            
            
              gradle
              
              
            
          
          // build.gradle
apply plugin: 'com.android.library'
android {
    ...
    defaultConfig {
        ...
        versionCode 1
        versionName "1.0"
        consumerProguardFiles "consumer-rules.pro"
    }
    buildTypes {
        release {
            minifyEnabled true // 开启混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'com.luffykou:android-common-utils:1.1.3'
}
        这里我创建的 library 功能非常简单,可以将一个图片 Bitmap 转成 Base64 字符串:
            
            
              java
              
              
            
          
          /**
 * GitLqr 工具类
 *
 * @author LQR
 * @since 2024/6/22
 */
public class GitLqrUtil {
    /**
     * bitmap 转 base64
     */
    public static String bitmapToBase64(Bitmap bitmap) {
        return Base64.encodeToString(bitmapToByte(bitmap), Base64.DEFAULT);
    }
    /**
     * bitmap 转 byte[]
     */
    public static byte[] bitmapToByte(Bitmap bitmap) {
        ByteArrayOutputStream o = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, o);
        return o.toByteArray();
    }
}
        现在就可以编译 library 生成 aar 文件了,找到在 AS 右侧的 Gradle 面板,点开后找到 library 下的 assembleXXX task,这里我需要生成混淆后的 aar 文件,所以执行 assembleRelease,最终产物在 module 的 build/outputs/aar 目录下:
三、发布本地 maven
因为 aar 文件中只包含当前 library 的代码和资源,其依赖的第三方库不会被合并进去,想要被其他工程正常集成使用,就需要将第三方库的依赖信息传递下去,所以,需要借助 maven 发布插件,生成 pom 文件,因为 maven 插件已经过时,这里我使用的是 maven-publish 插件,library 脚本配置如下:
            
            
              gradle
              
              
            
          
          apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
def LIB_VERSION_CODE = 1
def LIB_VERSION_NAME = "1.0"
def LIB_GROUP_ID = 'com.gitlqr'
def LIB_ARTIFACT_ID = 'closed_source_arr'
android {
    ...
    defaultConfig {
        ...
        versionCode LIB_VERSION_CODE
        versionName LIB_VERSION_NAME
    }
}
// 将当前module打包发布到本地maven仓库
afterEvaluate {
    publishing {
        // 配置maven 仓库
        repositories {
            // build/outputs/maven_repo
            maven { url uri(new File(buildDir, "outputs/maven_repo").path) }
        }
        // 配置发布产物
        publications {
            maven(MavenPublication) { // 容器可配置的信息 MavenPublication
                groupId LIB_GROUP_ID
                artifactId LIB_ARTIFACT_ID
                version LIB_VERSION_NAME
                // 注:AGP 3.6.0 及以上才能使用,作用是将 Android Gradle 插件生成的组件,作为发布的内容
                from components.release
            }
        }
    }
}
        如果 library 使用的 AGP 版本低于 3.6.0,maven-publish 的配置会比较麻烦,具体脚本配置如下:
            
            
              gradle
              
              
            
          
          task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "sources"
}
// 将当前module打包发布到本地maven仓库
afterEvaluate {
    publishing {
        // 配置maven 仓库
        repositories {
            // build/outputs/maven_repo
            maven { url uri(new File(buildDir, "outputs/maven_repo").path) }
        }
        // 配置发布产物
        publications {
            maven(MavenPublication) { // 容器可配置的信息 MavenPublication
                groupId LIB_GROUP_ID
                artifactId LIB_ARTIFACT_ID
                version LIB_VERSION_NAME
                // 配置上传源码
                artifact(sourceJar)
                // 指定生成的aar路径
                artifact "$buildDir/outputs/aar/${project.name}-release.aar"
                // pom文件中声明依赖,从而传递到使用方
                pom.withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')
                    // 必要的传递性依赖
                    def coreDependencies = ['api', 'implementation']
                    coreDependencies.each { dependency ->
                        def config = configurations[dependency]
                        println("lqr configurations = ${config}, class = ${config.class}")
                        // 提取每种传递性依赖配置中,依赖的第三方库信息
                        config.allDependencies.each {
                            def dependencyNode = dependenciesNode.appendNode('dependency')
                            dependencyNode.appendNode('groupId', it.group)
                            dependencyNode.appendNode('artifactId', it.name)
                            dependencyNode.appendNode('version', it.version)
                            // dependencyNode.appendNode('scope', dependency)
                        }
                    }
                }
            }
        }
    }
}
        - Android 上传库 官方文档:developer.android.com/build/publi...
 - maven 插件 和 maven-publish 插件的区别:juejin.cn/post/701760...
 
配置完成 maven 插件后,Gradle 面板会多出来 publishing 任务组,双击 publish 任务,即可在指定的本地目录下,生成 maven 相关的文件,其中 pom 文件非常重要,可以看到它的 <dependencies> 节点下,声明了 library 依赖的所有第三方库信息:
四、发布 jitpack
好了,现在 aar 和 pom 文件都有了,接下来就可以着手发布到 jitpack 了。
温馨提示:当前
pom文件非最终版本,下面的步骤,不要边看边操作,一定等完整看完之后再做操作哦~
1、创建仓库
首先,需要创建一个空白的 GitHub 仓库(名字随便),然后把 aar 和 pom 文件上传上去:
注:
pom.xml就是上面使用 maven 插件生成出来的closed_source_arr-1.0.pom文件,我把它名字改了而已。
可以看到,仓库中我多上传了一个 jitpack.yml 文件,这个文件的作用是,让 jitpack 直接使用我们提供的 aar 和 pom 文件,不需要它来生成,具体内容如下:
            
            
              yml
              
              
            
          
          install:
  - FILE="-Dfile=closed_source_arr-1.0.aar"
  - mvn install:install-file $FILE -DgroupId=com.gitlqr -DartifactId=closed_source_arr -Dversion=1.0 -Dpackaging=aar -DpomFile=pom.xml
        注:
jitpack.yml文件中的参数(file、groupId、artifactId、version)根据你的库来修改,不能照抄的!参数名很好理解,相信修改起来没有任何难度。
2、创建 release
给刚刚提交的记录打个 tag,并且基于这个 tag 发布一个 release:
注:因为
jitpack会以release的名字作为版本号,所以,建议最好跟aar的版本号一致。
3、构建版本
来到 jitpack.io/,将 GitHub 仓库链接拷贝到输入框,点击 Look up 按钮:
可以看到,刚刚打的 release 被识别到了,但是此时 Log 那一列下面没有日志图标,说明 jitpack 还没有对它进行构建,点一下 Get it 按钮,再 Look up 一下就触发构建了:
注:就算不点
Get it按钮,jitpack也会自动触发构建的,但不知道会延迟多久,反正你想马上构建的话,就点一下吧。
因为我们已经提供了 aar 和pom 文件,所以 jitpack 构建会很快,1 分钟左右就出来了,但是这次日志图标是红色的,后面是 Report 按钮,说明构建失败了:
注:
Status下方按钮后面有个 × 图标,如果你自己操作的时候没有看到的话,请确认是否有登录jitpack账号。
点击日志图标,可以查看日志信息:
看到可以到报错信息是 ERROR: No build artifacts found,这个报错是因为我们上传的 aar 和 pom 文件没有存放到 $HOME/.m2/repository 等标准目录下,所以 jitpack 找不到了。不过,可以给 pom 文件中声明构建时使用 android-maven-plugin 插件来解决:
            
            
              xml
              
              
            
          
          <?xml version="1.0" encoding="UTF-8"?>
<project>
  ...
  <packaging>aar</packaging>
  <build>
    <plugins>
      <plugin>
        <groupId>com.simpligility.maven.plugins</groupId>
        <artifactId>android-maven-plugin</artifactId>
        <version>4.1.0</version>
        <extensions>true</extensions>
        <configuration>
          <encoding>utf8</encoding>
          <source>1.8</source>
          <target>1.8</target>
          <sign>
            <debug>false</debug>
          </sign>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    ...
  </dependencies>
</project>
        - 最终 
pom文件内容:github.com/GitLqr/lib-... 
pom.xml 修改好之后,提交到 GitHub 仓库,然后,执行以下两个步骤:
- 把前面创建的 
release和tag都删掉,重新走第二步,即重新打tag和release。 - 在 
jitpack页面,点击Status下方按钮后面的 × 图标,将构建失败的记录删除,重新走第三步,即重新触发构建。 
这次日志图标是绿色的,说明构造成功了:
五、集成闭源 library
点击 Get it 按钮后,页面会向下滚动,按照 jitpack 的集成步骤,操作即可:
            
            
              gradle
              
              
            
          
          // root build.gradle
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
// app build.gradle
dependencies {
    ...
    // implementation project(":library")
    implementation 'com.github.GitLqr:lib-closed-source-arr:1.0'
}
        工程 rebuild 之后,能正常跑,查看 GitLqrUtil 类的引用,确实来自闭源 aar:
至此,闭源的 aar 就发布成功咯,如果你觉得文章对你有帮助的话,请不吝点个免费的赞~
如果文章对您有所帮助, 请不吝点击关注一下我的微信公众号:FSA全栈行动, 这将是对我最大的激励. 公众号不仅有Android技术, 还有iOS, Python等文章, 可能有你想要了解的技能知识点哦~