Android SDK开发 bintray aar嵌套aar aar合并 so库

需求

公司项目开发过程中会有一些公用的组件需要封装成SDK,方便给每个项目直接依赖使用。有个人的开源控件也一样。起初简单的控件SDK封装非常简单,不需要额外的依赖,直接使用Android原生的控件封装而成,或者是再加上一些support/androidx的依赖,还有就是三方库:RxJava、OkHttp、Glide等。

上面说的组件都是通过gradle-dependencies远程依赖的,我们应该知道一个区别:api和implementation之间的区别。

api:当前module可以使用,依赖当前module的module也可以使用。
implementation:只有当前module可以使用,其他module需要单独重新依赖才可以使用。

一般都用api,bintray上传的时候生成的pom文件会将api的依赖都写进去,这样当使用这个组件的时候,gradle会自动读取pom文件里面的额外依赖信息,自动将这些依赖组件下载到本地。

bintray上传插件:

  1. bintray-release
  2. gradle-bintray-plugin

问题

远程依赖会在pom文件中生成,但是aar依赖不会。例如这样:

api fileTree(dir: 'libs', include: ['*.aar'])

或者

api(name: 'aarFileName', ext: 'aar')

当你用正常上传方法,编译、上传后,新生成的aar文件解压后你是可以看到aarFileName.aar这个文件,但是你却使用不了里面的资源和类信息。

解决

我肯定不是第一个人遇到这种问题的人,但是为啥花费了我两天时间才搞明白这个呢?网上没有具体介绍这问题的解决方案,或者说我搜索的方式有问题?🤔🤔🤔总之没有一篇好的文章介绍这个问题。这也是我把标题写成这样的原因。。

强大的网友其实很早就已经遇到这个问题并有了解决方案,就是通过在gradle编译阶段增加合并aar的操作,将依赖的aar,aarFileName.aar解压后,把各种资源信息和自己开发的SDK组件内容合并放一块再打包成一个aar上传bintray。具体原理可以看gradle插件源代码,使用方法看README。

  1. android-fat-aar
  2. fat-aar-android
  3. fat-aar(推荐)

第一个最近更新是2017年,第二个近期都在维护但是我用起来R文件处理有问题,androidx包的资源id合并进来后总是报找不到的错误。所以推荐第三个。

第三个稍微也有个小问题,当它和bintray-release上传插件搭配的时候,会在pom.xml文件中默认加上aar依赖的信息,例子:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.ming</groupId>
  <artifactId>yan</artifactId>
  <version>2.1.0</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>androidx.appcompat</groupId>
      <artifactId>appcompat</artifactId>
      <version>1.1.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>3.10.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.2</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>io.reactivex.rxjava2</groupId>
      <artifactId>rxjava</artifactId>
      <version>2.1.12</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>androidx.recyclerview</groupId>
      <artifactId>recyclerview</artifactId>
      <version>1.1.0</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <artifactId>Sophonsdk</artifactId>
      <type>aar</type>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>*</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <artifactId>webrtclib</artifactId>
      <type>aar</type>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>*</artifactId>
          <groupId>*</groupId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

这样子的pom文件,当它被其他项目依赖的时候,因为aar依赖不能被获取,同步必定会失败,直接导致项目也就不能编译了。小明就绞尽脑汁看bintray-release插件的源代码,看他有没有对pom文件修改的方式。看了之后还真有,原理其实和gradle-bintray-plugin插件一样,因为用的api一样!都是maven-publish插件,此插件用法:

apply plugin: 'maven-publish'

直接上实现方式:

1.bintray-release

publish {
    artifactId = this.status//项目名称
    userOrg = rootProject.userOrg//bintray.com用户名
    groupId = rootProject.groupId//jcenter上的路径
    // publishVersion = rootProject.publishVersion//版本号
    publishVersion = this.version//版本号
    desc = rootProject.desc
    website = rootProject.website
    publications = ['MyPublication']
}

version '2.0.16-test'
status 'yan'

publishing {
    publications {
        MyPublication(MavenPublication) {
            artifact("$buildDir/outputs/aar/${this.status}-release.aar")
            groupId rootProject.groupId
            artifactId this.status
            version this.version
            // Define this explicitly if using implementation or api configurations
            pom.withXml {
                Node dependenciesNode = asNode().getAt('dependencies')[0] ?: asNode().appendNode('dependencies')
                // Iterate over the implementation dependencies (we don't want the test ones), adding a <dependency> node for each
                configurations.api.allDependencies.each {
                    // Ensure dependencies such as fileTree are not included.
                    println it.name
                    if (it.name != 'unspecified') {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                        dependencyNode.appendNode('scope', 'implementation')
                    }
                }
            }
        }
    }
}

2. gradle-bintray-plugin

bintray {
    user = rootProject.user
    key = rootProject.key
    publications = ['MyPublication']
    publish = true
    pkg {
        repo = 'maven'
        name = this.status
        userOrg = rootProject.userOrg
        licenses = ['Apache-2.0']
        vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git'
        version {
            name = this.version
            desc = 'Gradle Bintray Plugin 1.0 final'
            released = new Date()
            vcsTag = this.version
            attributes = ['gradle-plugin': 'com.use.less:com.use.less.gradle:gradle-useless-plugin']
        }
    }
}

version '2.0.16-test'
status 'yan'

publishing {
    publications {
        MyPublication(MavenPublication) {
            artifact("$buildDir/outputs/aar/${this.status}-release.aar")
            groupId rootProject.groupId
            artifactId this.status
            version this.version
            // Define this explicitly if using implementation or api configurations
            pom.withXml {
                Node dependenciesNode = asNode().getAt('dependencies')[0] ?: asNode().appendNode('dependencies')
                // Iterate over the implementation dependencies (we don't want the test ones), adding a <dependency> node for each
                configurations.api.allDependencies.each {
                    // Ensure dependencies such as fileTree are not included.
                    println it.name
                    if (it.name != 'unspecified') {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                        dependencyNode.appendNode('scope', 'implementation')
                    }
                }
            }
        }
    }
}

下面两段POM配置是不是一模一样。。区别主要是SDK基础信息的配置。

gradle-bintray-plugin插件不同的是不配置publishing,pom文件就不会主动添加api修饰的远程依赖。这样当别人依赖你的组件的时候还需要自己手动添加一遍所需的SDK了。

总结

填坑小能手 小明

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,135评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,317评论 3 397
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,596评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,481评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,492评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,153评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,737评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,657评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,193评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,276评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,420评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,093评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,783评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,262评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,787评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,427评论 2 359