android组件化打包module遇到的问题总结(打包成aar)

张开发
2026/4/9 7:58:54 15 分钟阅读

分享文章

android组件化打包module遇到的问题总结(打包成aar)
Android Studio打包AARhttps://blog.csdn.net/mozushixin_1/article/details/134159900-----------------------------------------------------步骤1、手动下载complie所引用的远程库gradle会把jar下载到本地。不要用-sources.jar的包2、合并依赖包3、 插件导入4、如何在后期增加ndkAShttps://blog.csdn.net/tantion/article/details/79675693本文中关于 api 和 implementation的说法应该是错的正确的说明请看https://blog.csdn.net/tantion/article/details/86623969-----------------------------------------------------------------------------------原文https://blog.csdn.net/u012345683/article/details/80118601在一开始接触APICLoud平台的时候我是拒绝的因为对于一个有着熟练的java技能掌握着老旧设计模式的人来说这种平台简直就是对于程序员这个职业的侮辱。第一个原因是APICLoud平台剥离了原生开发和htmljs开发的职责使得原生开发的职业方向越来越窄开发中的地位也逐渐下降第二个原因是这个平台完全是无脑式开发所有的js框架都是封装好的只需要像jQuery一样直接调用就好了APICLoud框架的设计使得前端开发者开发起来特别简单前端如果转apicloud开发成本会很低完全用不着设计模式。现在想想之前的想法过于偏激社会就是越来越现代化开发语言只是一种工具人都说君欲善其事必先利器。我觉得很有道理这些平台的发展就是为了减少开发人员的代码编写工作集中注意力在业务逻辑上也可以使得企业能够快速迭代产品从而减少运行成本安卓/ios开发一直都饱受着混合开发和RN开发的折磨现在这个APICLoud平台的出现我觉得是混合开发平台成熟的标志因为该平台不仅仅是混合开发的框架而且包含着混合开发的所有安卓/ios的第三方sdk的商店也就是api服务商业化模式这种模式对于开发人员的冲击是相当大的当sdk商店中已经集齐了所有满足日常的sdk的时候原生人员也就失业了因为所有的基础功能商店已经有前端只需要配置进apicloud框架就可以了企业的开发人员根本不需要重复造轮子可以把大量的时间放在业务逻辑上。在学习安卓原生的过程中让我明白了很多道理那就是这个世界唯一不变的是改变唯有不断的改变和学习才能跟的上时代的步伐授人以鱼不如授人以渔学习过程中也积累了很多学习经验学习效率明显得到了提高现在我马上要转到小程序和网页编写了想想也有点小激动呢经过一个礼拜的学习基本上可以做一些页面了路漫漫其修远兮吾将上下而求索。在自定义模块的时候出现的问题APICLoud的平台自定义模块上传需要的是aar包而aar包的特点就是内部会打包jar和jni里面的so文件但是不会把gradle的远程依赖下载并且打包进aar文件中这就需要手动下载complie所引用的远程库了。什么是gradle?Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置抛弃了基于XML的各种繁琐配置。面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala。他的功能是根据编写的gradle task来完成项目构建任务的我们android studio中的gradle文件就是用来编译我们的安卓项目的其中包含插件导入利用插件辅助编译多个编译文件合并操作引入远程仓库等等gradle的功能非常强大。gradle官网可以查看用法利用gradle来完成打包任务1、下载远程库电脑上安装一个gradle软件配置好环境变量。接下来就可以进行下载任务了。参考点击这里使用此方法下载Jar包的前提是已经配置好了Gradle的环境了配置好的标志是在终端输入gradle不提示command not found。1. 编写build.gradle文件代码apply plugin: java repositories { mavenCentral() jcenter() google() } dependencies { compile io.reactivex.rxjava2:rxjava:2.1.3 } task copyJars(type: Copy) { from configurations.runtime into lib // 目标位置 }2. 执行下载的指令gradle copyJars如果上述代码运行之后发现不能下载成功那么更换仓库地址使用国内镜像下载maven { url http://maven.aliyun.com/nexus/content/groups/public/ } //阿里镜像 maven{ url http://maven.aliyun.com/nexus/content/repositories/jcenter} //阿里镜像 mavenCentral() jcenter() google()2、合并依赖包1 libs下面的包合并一般我都是用代码编写一个task把所有dependencies{}括号包含的语句拆解成一句一句因为可能引用里面版本不一致就会导致下载下来的重名的jar或者aar会相互覆盖这个需要自己手动去排查版本比如说support包需要版本一致而okhttp和io-socket都引用了oki.jar包就是用代码让每一个依赖下载下来的文件都放在单独的一个文件夹然后自己手动去合并这些包到libs中这里一定要细心和耐心也要做到版本就低不就高。如果出现什么mutilclass , duplicate resource等等都是重复引用的导致的问题。2 so文件的合并问题so文件也需要手动去合并因为你自定义的module可能会和其他的module的so文件冲突这个就需要在android{}标签内加入packagingOptions { //jni包重复编译那么在这里配置包包含 或者不包含 exclude lib/mips/librsjni.so exclude lib/armeabi-v7a/libRSSupport.so exclude lib/arm64-v8a/librsjni.so exclude lib/arm64-v8a/libRSSupport.so exclude lib/x86_64/libRSSupport.so exclude lib/mips/libRSSupport.so exclude lib/x86/librsjni.so exclude lib/x86_64/librsjni.so exclude lib/armeabi-v7a/librsjni.so exclude lib/x86/libRSSupport.so }还要一个就是其他module有的兼容版本你没有那么就需要手动复制兼容版本文件夹把对应的文件导入比如APICLOUD平台只有而你的module有x86 armeabi64 armeabi和armeabi-v7a cpu版本兼容那么在编译的时候就会包含四个文件夹而其他module只有两个那么就会运行时就会缺包如果是这种情况那么就把自己的包x86 armeabi64 删掉或者在 defaultConfig{}标签内加入ndk { abiFilters armeabi-v7a, armeabi }这样编译的时候就只会保留 “armeabi-v7a”, armeabi文件夹。关于so文件兼容请看链接内容3 插件导入插件是gradle运行的环境前提条件比如说apply plugin: com.android.library apply plugin: com.jakewharton.butterknife这里的意思就是说当前gradle的任务是把这个module当成是library来编译在运行gradle之前加载butterknife插件至于如何配置butterknife的话这里不细说但是要把module打包成aar的话加载butterknife插件必须本地加载因为aar不会自动下载远程依赖的同理使用第一步所说的下载butterknife所需要的jar包将它们放入lib注意是新建的文件夹。然后在gradle的根部添加如下代码//展开libs文件夹里面的文件aar文件依赖必须的配置 repositories{ flatDir{ dirs libs } } /* buildscript这是gradle环境本身所依赖的库一般是链接 maven和git,Jcenter的仓库加载插件的但是这里必须本地加载 下面是把所有的lib文件中的文件加载进去*/ buildscript { dependencies { classpath fileTree(include: [*.jar], dir: lib) } }2、项目合并上面只是仅仅把module中所有的jar和aar都合并进去了接下来还要考虑不同的module直接依赖冲突的问题先来了解下gradle依赖的几个关键字Android Studio引用第三方库很方便只需要一句代码就可以搞定几种引用第三方库的方式总结一下 方式:1它就会自动把这个包下载下来并且引用它。节省git空间而且修改版本也很方便。 compile com.android.support:support-v4:23.3.0 方式2引用libs下所有jar包 compile fileTree(dir: libs, include: [*.jar]) 方式3引用一个jar compile files(libs/fastjson-1.1.53.android.jar) 方式4引用一个aar文件注意并不能像 方式2 那样自动引用全部的aar而需要对每个aar分别进行引用。 compile(name: aar_file_name, ext: aar) 方式5引用库类型的项目 compile project(:xxxsdk) 方式6仅仅在编译时使用但最终不会被编译到apk或aar里 provided files(libs/glide-3.7.0.jar)经过本人实验貌似是资源文件在打包编译的时候如果重名就会覆盖而class文件重名就是直接编译报错所以资源文件冲突是隐形的class冲突比较明显。jar冲突的话让主module依赖这个jar其他次module使用provided 关键字依赖这个jar包这样编译的时候就只有一份。aar冲突比较麻烦了因为aar中可能会包含jar文件这样的话就需要查看官方文档或者自己解压缩文件去查看这个aar里面究竟包含着那些jar文件利用 exclude group:, module: 语句来排除jar被编译进aar包中。例如最后如果是资源文件冲突最常见的的错误就是no resource id found或者是java.lang.NoSuchFieldError: No static field xxx of type I in class Lcom/XX/R$id; or its superclasses要么就是多个module的资源文件重名导致相互覆盖那么就找不到指定的资源要么就是指定的控件ID重名多个重名控件导致找不到控件解决办法也很简单就是改文件或者控件名字。比如说我在APICLOUD云平台编译的时候出现以下错误What went wrong: Execution failed for task :app:transformClassesWithJarMergingForRelease . com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: android/support/v4/app/BaseFragmentActivityDonut.class意思就是class文件重复原因就是apicloud的框架本身自带v4包而我的module也有v4包在引入我的自定义模块后打包的时候就会出现相同的两个class文件这样就出现了以上错误解决的办法上面已经说了使用exclude语法将相应的部分排除这个方法只能排除网络库本地的还没发现能够有效起到作用因此我在想既然apicloud框架本身自带v4的class文件而我自定义模块打包成aar文件又不会把v4.aar打包进去还是要手动将v4.aar放到和module.aar同目录下那么我可以不将v4.aar放入而是使用apicloud框架自带的v4.aar这样就巧妙的将重复问题解决了。记录下这个问题。新版gradle的新语法Gradle 3.4 引入了新的依赖配置########################### 这种说法应该是错的 begin ###########新增api 和 implementation 来代替 compile 依赖配置。其中 api 和以前的 compile 依赖配置是一样的。使用 implementation 依赖配置会显著提升构建时间因为implementation只会依赖直接引用的资源而资源本身所依赖的资源是不会去深度依赖这样就减少了依赖编译所消耗的时间。比如A依赖B B依赖C 。A implementation B只会将B加入编译。而 A api B或者A compile B就不仅仅只编译B也会将C加入编译。所以在使用implementation 依赖的时候不要惊讶找不到类找不到资源之类的事情因为他的原理就是不深度依赖。要么使用api在高版本建议使用这个和complie低版本。要么自己手动在A中将所需要的资源都依赖过来。implementation和api的区别还有就是在moduleB中如果使用implementation来引用网络或者本地资源moduleA 依赖 moduleB这样写的话还是找不到如果moduleB api来依赖网络或者本地资源那么这些资源就可以被moduleA找到并使用。########################### 这种说法应该是错的 end ###########正确的说明请看https://blog.csdn.net/tantion/article/details/86623969新增compileOnly provided gradle 添加依赖到编译路径编译时使用。不会打包到APKruntimeOnly apk gradle 添加依赖只打包到 APK运行时使用。不会添加到编译路径现在外国服务器相当不稳定经常性的连接不上他们的中央仓库所以自己收藏了几个国内的镜像速度非常快。maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/’ }maven{ url ‘http://maven.aliyun.com/nexus/content/repositories/jcenter’}经常会出现merge task失败的问题 Task [App] not found in root project [project_name] 这种问题一般可以去查找aar资源包内是否有重复的jar依赖导致合并编译出来的jar失败但是aar重复并不会导致这个问题不知道谷歌是哪根经出了问题。

更多文章