欢迎光临
专注android技术,聚焦行业精粹,传扬中国传统文化,我们一直在努力

fat-aar 实现分析

1、fat-aar介绍

简单的说他可以把一个android library工程所依赖的module(包含远程依赖)的内容(包括:jar, assets, res,jni, manifest等)在打包时都包含进来,最终生成一个完整的aar,可以单独提供出去使用。

fat-aar非常方便,尤其当你所依赖的库不公开,或者对方无法访问你的传递依赖库时,又或者对方不会使用gradle依赖,只会拷贝资源到eclipse工程中时非常有用。

注意:fat-aar使用方面会有一些限制,fat-aar只会处理embedded关键字指向的这层一级依赖,而它的再下一层的依赖则不会处理。对于这个问题fat-aar也提供了一个publish.gradle来处理,也就是说最终你发布的aar虽然是单独的一个,但是随之也会有一个pom文件告诉接入方还有一些子依赖。所以接入方还得用gradle方式去接入,以保证这些子依赖可以完整的下载下来。

具体使用很简单,参考github的原仓库介绍:链接

步骤如下:

第一步:导入fat-aar.gradle

有两种方式:

1.可以拷贝fat-aar.gradle到你的library工程目录,在你的build.gradle里面导入即可:

fat-aar的下载地址:链接 ,或者到上面的github原项目直接下载

2. 也可以通过url来导入fat-aar

第二步: 定义需要合并的 embedded 依赖

你需要修改build.gradle里面的dependencies块,把你想要合并进来的aar依赖前面的compile字段改为embedded。修改的结果例如下面这样:

依赖的前面有embedded 将会被合并进来,其它的会保持gradle原来的依赖方式。

第三步: 同一个工程依赖这个embedded工程需要移除传递依赖

经过上面两步你已经将子工程embedded到了你的主library工程了。但你会发现的你的application类型的工程在依赖(compile)你的这个工程时会提示类重复错误,原因是在类型为application的工程compile你的library时也会把该library的传递依赖也包含进来,此时你的library如果使用了fat-aar,那么实际你的library也包含了这些传递依赖,所以会出现类重复。你需要确保其它application类型的工程在依赖你已经使用embedded的library工程(简单称为:fat-library)时不开启传递依赖(transitive)。

如果你再同一个工程里面使用了这个fat-library,你需要简单的定义你的fat-library工程的依赖为non transitive:

3、fat-aar实现分析

按照上面的步骤我们创建一个fat-library并embedded两个aar工程:library-one和library-two,build.gradle的dependencies配置如下:

3.1、fat-aar的配置阶段流程分析

fat-aar的配置流程是在gradle的afterEvaluate里面实现的,以下是对afterEvaluate的介绍:

在所有build.gradle解析完成后,开始执行task之前,此时所有的脚本已经解析完成,task,plugins等所有信息可以获取,task的依赖关系也已经生成,如果此时需要做一些事情,可以写在afterEvaluate

fat-aar在这里做的事情主要包括2件事情:

  • 将所有embedded的aar里面的artifact(包括:aar或jar)文件都放在正确的目录,并记录它们的位置
  • 对fat-aar自定义的task配置好dependsOn,也就是依赖的先后顺序

接下来详细的介绍afterEvaluate里面的每个流程点:

 

1. 获取embedded的所有直接依赖

这里使用的是这样的代码:

其中embedded是自定义的一种configuration, 然后通过dependenciesembedded配置的依赖 compile进来,具体实现如下:

firstLevelModuleDependencies的官方解释如下:

Returns the {@link ResolvedDependency} instances for each direct dependency of the configuration. Via those
you have access to all {@link ResolvedDependency} instances, including the transitive dependencies of the
configuration.

返回configuration对应的直接依赖。通过这些直接依赖你可以访问所有的依赖实例,包括configuration的传递依赖

2. 获取每一个依赖的aar artifact路径

注意这里会由于工程的配置不同而导致最终生成的aar包经常出现以下两个问题:

问题1:如果你的gradleApiVersion >=2.3 , fat-aar默认会在build/intermediates/bundles/default目录下面去找,但是我们工程的目录bundles下面只有release,该怎么解决?:

问题2:aarPath是否可以修改?我想改一下这些临时文件的地方,方便clean时统一清除

问题1分析:我理解fat-aar设计的初衷只针对release环境的library 工程,而在gradleApiVersion >=2.3时,gradle构建时多了一个default目录的概念,而此版本之前都是release,debug等。而fat-aar代码中写死了2.3用default:

这样的话如果library工程使用了publishNonDefault 并设置为true,则构建时不再是default目录,而是release目录了

publishNonDefault配置的作用: 是否关闭默认发布配置 (true关闭, false开启)
因此最先想到的是: 关闭默认发布配置, 即将publishNonDefault设为true (言外之意, library的buildType会和主module的buildType保持一致了).

解决办法:修改bundle_release_dir和aarPath变量的default为release,具体如下图:

 

问题2分析:aarpath不要修改它的路径(问题1提出的修改除外),我们讲一下它的作用,然后你就明白怎么正确的使用它了

aarPath的生成规则:aarPath是fat-aar 中每一个dependency的artifact所在的目录,最终fat-aar打aar时会它收集的所有aarPath(embeddedAarDirs)里面的资源都合并起来。这些aarPath 如果是本地project,它会按照下面的方式拼接找到它的aarPath:

问题2隐藏的风险:有时你发现aarPath下面找不到artifact资源,这个是什么情况呢? 很多情况下你的project里面的目录名称和moduleName不是一致的,例如你改了moduleName让它更容易理解,那么此时fat-aar会仍然根据moduleName去找artifact目录(因为fat-aar认为moduleName即project目录名称),那么此时就找不到了。但如果你了解了aarPath的生成规则,你就不难发现此问题了。

 

3. 获取当前gradle版本对应的aar文件路径

依赖的aar路径随着gradle的版本不同而不同:

得到的aarPath是该gradle版本下依赖的aar资源的存放路径,注意当gradle版本>=2.3时默认aar会下载到本地C盘的.gradle/caches目录,这里做了一步操作就是定义了一个新的目录赋值给aarPath,接下来会把C盘目录下面下载的aar资源拷贝到当前工程的aarPath目录下面。

4.获取dependency的所有moduleArtifacts

我们知道每个dependency会包含可能多个artifact(就是具体依赖的aar或jar文件),步骤3,4,5就是把这些artifact路径记录下来,对于gradle版本>=2.3时会把artifact从C盘拷贝到当前指定的aarPath里面。这一步为接下来的aar合并做铺垫。

5、配置fat-aar自定义的task与gradle task的依赖关系和先后顺序

我们知道生成aar的最直接task是bundleRelease或者bundleDebug等,由于fat-aar只处理release类型,所以fat-aar所有自定义的task都是在hook bundleRelease的子任务,这样最终改变bundleRelease的最终输出,生成一个我们想要的一个聚合了所有embedded资源的aar包。详细的task 依赖关系请参考下面的3.2节。

3.2、fat-aar task依赖关系

蓝色为gradle自带的task,红色为fat-aar自定义的task。从图中可以看出来fat-aar主要对bundleRelease(打aar包的task)的子任务hook,这些子任务包括assets,resources,jni,manifest,java,R,proguard这些组成aar的必要资源的处理任务。通过hook将这些资源整合成fat-aar需要输出的一个聚合aar包。下面对这些task分别做分析:

 

处理资源类型task名称依赖的gradle task功能
assetsembedAssetsprepareReleaseDependencies将所有embedded方式依赖的aar路径中assets目录追加到当前的fat-library工程对应的目录中来(android.sourceSets.main.assets.srcDirs+=file("$aarPath/assets"))
proguardembedProguardprepareReleaseDependencies将所有embedded方式依赖的aar路径中proguard.txt 中的内容append到当前的fat-library的proguard.txt里面
resembedLibraryResources依赖:
embedProguard
prepareReleaseDependencies

被依赖:
packageReleaseResources
首先找到bundleRelease打res资源的task(packageReleaseResources)的输入,然后往输入中添加aar路径中的资源目录($aarPath/res)
jniembedJniLibstransformNativeLibsWithSyncJniLibsForRelease将所有embedded方式依赖的aar路径中jni目录($aarPath/jni)中的文件拷贝到当前的fat-library工程对应的jni目录中来
manifestembedManifestsprocessReleaseManifest将embedded library里面的manifest和当前fat-library的manifest合并(使用ManifestMerger2),输出替换当前工程的manifest.xml和替换aapt生成的manifest.xml(即:build/intermediates/manifests/aapt/release/AndroidManifest.xml)
R.javagenerateRJavaprocessReleaseResources
被依赖:collectRClass, embedRClass,embedJavaJars
该task负责把embedded依赖的aar工程里面的R.java的资源id引用都指向当前library工程(fat-library)的R.java文件里面来。
JavaembedJavaJarscompileReleaseJavaWithJavac1.将所有embedded方式依赖的aar路径中classes.jar里面的class拷贝到fat-library的build/intermediates/classes/release目录下面
2.将所有embedded方式依赖的aar路径中libs目录下面的jar文件拷贝到当前fat-library的build目录下面(fat-library/build/intermediates/bundles/default/libs)
3.将所有embedded方式依赖的jar artifact也拷贝到当前的fat-library的build目录下面(同上)


3.2.1、embedManifests task

一张图来描述embeddedManifest task的流程,一句话总结这个流程是将embedded library里面的manifest和当前fat-library的manifest合并,输出替换当前工程的manifest.xml和替换aapt生成的manifest.xml(即:build/intermediates/manifests/aapt/release/AndroidManifest.xml)

 

3.2.2、generateRJava task

功能描述:generateRJava是dependsOn processReleaseResources该task负责把embedded依赖的aar工程里面的R.java的资源id引用都指向当前library工程(fat-library)的R.java文件里面来。如果不执行generateRJava会怎么样呢?我们单独执行processReleaseResources task,打开library-onefat-library的R.java是这样的

library-one:

fat-library:

执行完generateRJava task后,library-one的R.java会在上面结果的基础上将资源ID指向了fat-library工程的资源id,最终library-one的R.java如下:

library-one:

 

实现分析:

找到fat-aar里面的generateRJava task

首先它会获取当前fat-library工程的包名

它会先找到当前fat-library工程的manifest文件路径,android.sourceSets.main.manifest.srcFile 返回的是xxx\src\main\AndroidManifest.xml ,如果Manifest文件存在则读取里面的package属性,并存放在libPackageName变量中。这个libPackageName在后面逻辑中用于embedded工程(library-one和library-two)的R.java中的资源ID指向fat-library的R.java资源ID时使用。

上面这段代码是把遍历embedded的aar依赖,把他们的R.txt种的subclassnametype读取出来存放在Map。注意这里没有存放value,是因为此时fat-library的R.java已经包含了所有依赖的aar工程的资源ID值了,这里仅仅是为后续用subclass, nametype来映射到这些值

接下来上面的代码是用Map来生成该embedded aar(例如:library-one)工程的R.java文件,我们可以看到这个R文件路径就是根据该embedded aar的包名创建的。

3.2.3、fat-aar如何实现将R.class合并

上面介绍了generateRJava task,它的任务是做R文件合并和关联。但最终的aar包里面是如何包含这些R.class 的呢?我们来一张图描述generateRJava和其它task的关系:

每个task职责如下:

generateRJava: 做R文件合并和关联。将所有embed进来的aar里面的R文件都指向最外层的R文件。这样不会出现每个aar无法找到自己资源的情况了。

collectRClass: 将上面的R.class拷贝到build目录下面的fat-aar/release目录

embedRClass: 将build/fat-aar/release目录下面的R.class打包成Jar并输出到“build/intermediates/bundles/default(或者release)/libs”下面

embedJavaJars: 合并所有embed方式依赖的aar和jar里面的jar包(包括:classes.jar, libs里面的jar),并输出到“build/intermediates/bundles/default(或者release)/libs”下面

 

遇到的问题:

  1. 我曾今遇到过在“build/intermediates/bundles/default(或者release)/libs”居然没有任何jar文件的错误,这个原因是transformClassesAndResourcesWithSyncLibJarsForRelease task会清除libs下面的jar。具体为什么会清除我还不清楚,希望知道的同学可以回复本文章。

解决方法:

a. 在embedJavaJars task末尾将libs里面的内容拷贝到一个临时目录(例如:libs_tmp), 代码如下:

b. 并在打aar包之前将libs_temp目录里面的内容复制回来,代码如下:

 

 

赞(6) 打赏
未经允许不得转载:花花鞋 » fat-aar 实现分析

评论 33

  1. #1

    Incredible! This blog looks exactly like my old one!

    It’s on a totally different topic but it has pretty much
    the same layout and design. Outstanding choice of colors!

    Cialis5年前 (2019-04-04)回复
  2. #2

    Helpful information. Lucky me I discovered your website by chance, and I
    am stunned why this twist of fate did not took place earlier!
    I bookmarked it.

    minecraft5年前 (2019-04-14)回复
  3. #3

    I’m pretty pleased to uncover this website. I wanted to thank you
    for your time for this particularly fantastic read!! I definitely
    appreciated every bit of it and i also have you bookmarked to check out new stuff in your website.

    tinyurl.com5年前 (2019-04-14)回复
  4. #4

    Hey there just wanted to give you a quick heads up. The text in your content seem to be
    running off the screen in Firefox. I’m not sure if
    this is a format issue or something to do with
    internet browser compatibility but I thought I’d post to let you know.
    The layout look great though! Hope you get the problem fixed soon. Thanks

    minecraft5年前 (2019-04-15)回复
  5. #5

    Cool blog! Is your theme custom made or did you download it from somewhere?
    A theme like yours with a few simple adjustements would really make my blog stand out.
    Please let me know where you got your design. Cheers

    minecraft5年前 (2019-04-18)回复
  6. #6

    Hello, Neat post. There is a problem together with your web site in web explorer, would check this?
    IE nonetheless is the marketplace leader and a big portion of other people will omit your
    fantastic writing due to this problem.

    tinyurl.com5年前 (2019-04-18)回复
  7. #7

    It’s nearly impossible to find experienced people on this subject, however, you seem like you know what you’re talking about!
    Thanks

  8. #8

    Hey very nice web site!! Man .. Excellent .. Superb ..
    I will bookmark your web site and take the feeds additionally?
    I am satisfied to find so many useful information right here within the post, we want develop more techniques in this regard, thanks for sharing.
    . . . . .

    minecraft5年前 (2019-04-19)回复
  9. #9

    I like the helpful information you supply in your
    articles. I’ll bookmark your blog and take a look at once more here
    regularly. I’m rather certain I will learn plenty of new stuff
    right here! Best of luck for the following!

    minecraft5年前 (2019-04-20)回复
  10. #10

    Zithromax Iron Interaction Para Que Sirve El Cialis De 5 Mg Buy Propecia Cheap Online Uk cialis 40 mg Kamagra Vendita Camerun Prix Amoxicillin 10

    LesTheacy5年前 (2019-04-20)回复
  11. #11

    Remarkable things here. I’m very happy to see your post.
    Thanks so much and I am looking forward to contact
    you. Will you please drop me a mail?

    minecraft5年前 (2019-04-21)回复
  12. #12

    Since the admin of this site is working, no hesitation very
    soon it will be famous, due to its quality contents.

    minecraft5年前 (2019-04-21)回复
  13. #13

    Thanks for a marvelous posting! I really enjoyed reading it, you might be a
    great author. I will ensure that I bookmark your blog and may come back later in life.
    I want to encourage you to ultimately continue your great job, have a nice holiday weekend!

    minecraft5年前 (2019-04-22)回复
  14. #14

    Excellent site. Plenty of useful information here. I’m sending it to a few buddies ans additionally sharing in delicious.
    And certainly, thank you to your effort!

    minecraft5年前 (2019-04-23)回复
  15. #15

    Hi there! I know this is kind of off topic but I was wondering if you knew
    where I could locate a captcha plugin for my comment form?

    I’m using the same blog platform as yours and I’m having trouble finding one?
    Thanks a lot!

    minecraft5年前 (2019-04-24)回复
  16. #16

    May I simply just say what a relief to uncover somebody that genuinely knows what they are talking about on the net.
    You certainly understand how to bring a problem to light and
    make it important. More people really need to look at this and understand this side of the story.
    I was surprised you are not more popular given that you surely have the
    gift.

    minecraft5年前 (2019-04-24)回复
  17. #17

    哇塞,居然是沙发?留个名

    酥酥影院5年前 (2019-05-05)回复
  18. #18

    Hi mates, how is all, and what you wish for to say about this post, in my view its in fact
    awesome in support of me.

    gamefly free trial5年前 (2019-05-20)回复
  19. #19

    Hi there! This is kind of off topic but I need some
    advice from an established blog. Is it hard to set up your
    own blog? I’m not very techincal but I can figure things out pretty
    fast. I’m thinking about setting up my own but I’m not sure where to start.
    Do you have any ideas or suggestions? Many thanks

    gamefly free trial5年前 (2019-05-23)回复
  20. #20

    First off I would like to say fantastic blog! I had a quick
    question that I’d like to ask if you don’t mind.
    I was curious to find out how you center yourself and
    clear your head prior to writing. I’ve had trouble clearing my
    mind in getting my ideas out. I do enjoy writing however it just seems like the first 10 to 15 minutes are generally wasted just trying
    to figure out how to begin. Any suggestions or hints? Thanks!

  21. #21

    Thank you for the auspicious writeup. It in reality
    was once a amusement account it. Glance complicated to far delivered agreeable from you!
    However, how can we keep up a correspondence?

  22. #22

    Aw, this was an incredibly good post. Finding the time and actual effort to create a good article… but what can I
    say… I procrastinate a lot and never seem to get nearly anything done.

    https://pomodorr.com/5年前 (2019-05-31)回复
  23. #23

    This is the right website for everyone who wants to understand this topic.

    You understand a whole lot its almost hard to argue with you (not that I
    actually will need to…HaHa). You definitely put a brand new spin on a
    topic that has been written about for many years.
    Wonderful stuff, just great!

    P.S. If you have a minute, would love your feedback on my new website re-design. You can find it by searching for “royal cbd” – no sweat if you can’t.

    Keep up the good work!

    Justin4年前 (2020-04-17)回复
  24. #24

    I’m really enjoying the theme/design of your blog.

    Do you ever run into any web browser compatibility problems?
    A few of my blog audience have complained about my blog not operating correctly in Explorer but looks great in Opera.
    Do you have any recommendations to help fix this issue?

    Royal CBD4年前 (2020-05-12)回复
  25. #25

    I visited many web sites but the audio feature for audio songs
    existing at this website is in fact fabulous.

    Unsolvedmurderswiki1年前 (2022-11-14)回复
  26. #26

    I could not resist commenting. Perfectly written!

  27. #27

    This article will help the internet visitors for setting up new website
    or even a weblog from start to end.

  28. #28

    Greetings! I know this is kinda off topic but I was wondering if you knew where I could get
    a captcha plugin for my comment form? I’m using the same blog platform as yours and I’m having trouble finding
    one? Thanks a lot!

  29. #29

    I’m truly enjoying the design and layout of your blog. It’s a
    very easy on the eyes which makes it much more pleasant for me to come here
    and visit more often. Did you hire out a designer to create your theme?
    Fantastic work!

  30. #30

    Very good post. I’m facing many of these issues as well..

  31. #31

    Hey there! I could have sworn I’ve been to this blog before but after checking through some of the post I realized it’s new to me.
    Nonetheless, I’m definitely delighted I found it and
    I’ll be bookmarking and checking back often!

  32. #32

    Hey! I’m at work browsing your blog from my new iphone 3gs!

    Just wanted to say I love reading your blog and look forward to all your posts!
    Keep up the fantastic work!

  33. #33

    Thank you for the good writeup. It in reality was once a amusement account it.
    Look advanced to far delivered agreeable from you!
    However, how can we communicate?

国内精品Android技术社区

专注android技术,聚焦行业精粹,传扬中国传统文化,我们一直在努力

联系我们

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

登录

找回密码

注册