apk->aar

原项目结构

moduleA:主要sdk和对sdk封装,还有一些基础库封装。

muduleB:相对独立模块,对其他模块无依赖。

moduleC:主module,包括UI及业务,依赖moduleB,非直接依赖moduleA(反射调用)

需求

整个项目原本是作为应用存在,现在需要打包成sdk,提供给其他应用使用,需要包含UI及全部功能。

简单拆分

1.moduleA、muduleB、moduleC 打包到一个aar。
2.工程既需要打包aar,又需要打包apk,所以moduleC不能再作为application存在,moduleC 属性变成library。
3.新增空壳moduleD,处理作为应用的职责,属性application,当打包sdk时,此module用来验证aar功能,打包应用时,此moudle作为应用指责存在

所以现项目结构:

moduleA: library

muduleB: library

moduleC: library

moduleD: application

开工

三个module需要打包到一个aar

方案一:fat-aar,

最原始的项目已经无人维护,https://github.com/kezong/fat-aar-android 算是比较新,可以用的,使用方式见github。

fat-aar的原理:

aar本身就是压缩包,有时候为了减小包体积,会把三方库中的so删掉,只留v7a平台的,所以aar可以直接进行增删合并等文件操作,没有apk那么麻烦,反编译后需要重新打包。

fat-aar的原理其实就是根据aar中的文件类型进行文件合并,在fat-aar.gradle中大体可以看到。

generateReleaseAssets.dependsOn embedAssets
embedAssets.dependsOn prepareReleaseDependencies

// Embed Resources by overwriting the inputResourceSets
packageReleaseResources.dependsOn embedLibraryResources
embedLibraryResources.dependsOn prepareReleaseDependencies

// Embed JNI Libraries
bundleRelease.dependsOn embedJniLibs

if(gradleApiVersion >= 2.3f) { //gradle版本不一致的处理
    embedJniLibs.dependsOn transformNativeLibsWithSyncJniLibsForRelease
    ext.bundle_release_dir = "$build_dir/intermediates/bundles/default"
}else{
    embedJniLibs.dependsOn transformNative_libsWithSyncJniLibsForRelease
    ext.bundle_release_dir = "$build_dir/intermediates/bundles/release";
}

// Merge Embedded Manifests
bundleRelease.dependsOn embedManifests
embedManifests.dependsOn processReleaseManifest

// Merge proguard files
embedLibraryResources.dependsOn embedProguard
embedProguard.dependsOn prepareReleaseDependencies

// Generate R.java files
compileReleaseJavaWithJavac.dependsOn generateRJava
generateRJava.dependsOn processReleaseResources

// Bundle the java classes
bundleRelease.dependsOn embedJavaJars
embedJavaJars.dependsOn compileReleaseJavaWithJavac

// If proguard is enabled, run the tasks that bundleRelease should depend on before proguard
if (tasks.findByPath('proguardRelease') != null) {
    proguardRelease.dependsOn embedJavaJars
} else if (tasks.findByPath('transformClassesAndResourcesWithProguardForRelease') != null) {
    transformClassesAndResourcesWithProguardForRelease.dependsOn embedJavaJars
}

支持合并的文件如下

  •  productFlavors
  •  manifest merge
  •  classes jar and external jars merge
  •  res merge
  •  assets merge
  •  jni libs merge
  •  proguard.txt merge
  •  R.txt merge
  •  R.class merge

fat-aar遇到的问题:

1. 找不到R文件,drawable,style等

使用方式不对

开始将moudleA 使用embed方式打包为一个aarA,moudleB使用embed方式打包为一个aarB,moudleC依赖aarA,aarB使用embed方式打包到最终的sdk,R文件丢失,程序异常。

修复:只需要处理moduleC的gradle文件即可,moudleC使用fat-aar插件,embed moudleA 和 moudleB,注意,AB两个module中依赖的aar都要在moduleC中调用embed依赖,这样才会把所有依赖的aar打到最终的sdk中。

2. aar中资源文件重名,如app_name

  • 组件原则中提到每个组件资源名称需增加前缀,防止命名重复,导致资源冲突。
  • 最好修改重名资源,防止资源异常。
  • 实在不想修改,在gradle.properties中增加 android.disableResourceValidation = true 忽略此错误

3. jar包非java文件资源丢失

项目中依赖了mqtt的jar包,jar包中有Resource Bundle非java文件,编译出来的aar中,此部分文件丢失,导致应用异常。

修改为依赖远程库解决

4. Butterknife

Butterknife在组件化开发中显得有点睿智,存在Library中需要使用R2文件,普通的Library还行,但是需求是技能打包aar,又能打包apk,这部分不能动态切换,比较麻烦,最终忍痛移除了Butterknife的依赖项,手动findViewById解决。

5.关于jar包的依赖

依赖的jar包都在aar中的lib目录中,打包的时候可以不关心jar包打不打进去,如果提供给外部使用的时候有重复jar包引用,只需要把aar中jar包删掉即可,不需要重复打包。

一套代码维护两种打包方式

主要就是gralle和shell脚本编程。

1. 动态替换manifest占位符,因为作为Library,启动Activity不能有Launcher和main属性。

2. 使用fat-aar的制作gradle文件抽取独立脚本,正常依赖不使用fat-aar编译。

3. gradle.proterties中定义开关,是否打包sdk,build.gradle中指向编译方向,调用fat-aar脚本,还是正常编译。

4. 打包aar shell脚本,自动打包aar上传。

方案二:maven私服

把依赖的aar全部上传到maven私服,打包aar生成的pom文件依赖,外部使用时使用transitive = true,即可以自动下载依赖项。目前项目中没有使用此方案,虽然有maven私服,但非公共库不宜上传,而且众多aar版本管理更新也比较麻烦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值