栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android 将多个模块生成一个 AAR 后提供 SDK

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 将多个模块生成一个 AAR 后提供 SDK

Android Gradle 打包每个库工程都会导出一个 AAR 文件。之前有尝试使用第三方插件 fat-aar 来合并打包,但打包时经常报错,合并时间也略长。此外此次导出的 SDK 需要做代码混淆,如果对每一个库都进行混淆文件非常麻烦,不便于统一管理,也不便于统一暴露接口。工程库之间的引用逻辑比较多,也增加了导包的配置成本,此外还要支持 AIDL 合并。

GitHub源码地址:https://github.com/RuiRay/MergeModuleAAR

这里选择将多个工程库合并到一个工程库后再打包的方式实现。

合并支持:

源代码和资源文件:java/aidl/assets/libs/res清单文件:AndroidManifest.xml添加资源前缀(支持drawable/layout/string等类型,暂不支持style类型)统一包名,和BuildConfig、R包名路径的替换;多模块的合并,绝对路劲使用 path> 开头;自定义标签动作,如 //MergeReplaceNext> 用注释内容替换下一行;DataBinding 生成 findViewById() 代码;
javaMerge 快速使用

请先下载jar文件: MergeModuleAAR/produce/script/javaMerge.jar

java -jar javaMerge.jar $ProjectPath "$ProjectPath/produce" $PACKAGE_NAME $RES_PREFIX "exo" ${MergeModuleName[*]}

具体使用参数参见: /MergeModuleAAR/produce/script/runSDK.sh

javaMerge 项目在 IDEA 中运行步骤

打开 IDEA 编辑器;File -> Open,选择 javaMerge 目录导入;File -> Project Structure:

Project Setting -> Project:

Project SDK: Java1.8Project language level: 8 - Lambdas ... etc.Project compiler output: $projectPath/javaMerge/out Project Setting -> Modules:

选中左侧的 javaMerge右侧中选择 Sources 卡片标签选中目录中的 src,右键操作窗中选择 Sources。(此时右侧 SourceFolders 看到 src 即正常); Project Setting -> Libraries:

点击上面 + 号,选择 Java文件选择框中选择 ../javaMerge/lib/*.jar(全选所有jar)点击OK 打开 OneSetup.kt 文件,运行;

或使用 kotlin 命令行编译,具体参考:https://www.runoob.com/kotlin/kotlin-command-line.html



代码实现逻辑 一、遍历读取需要合并的文件名

分析需要合并的文件,包含 libs/、src/main/ 和 build.gradle 文件。不需要合并的文件,例如:build/、test/ 等。

方便起见,代码中定义了需要读取文件的目录:

ItemFile("libs"),
ItemFile("src").addItemFile(
        ItemFile("main").addItemFile(
                ItemFile("aidl"),
                ItemFile("assets"),
                ItemFile("cpp"),
                ItemFile("java"),
                ItemFile("jniLibs"),
                ItemFile("res"),
                ItemFile("res-night"),
                ItemFile("AndroidManifest.xml", false)
        )
),
ItemFile("build.gradle", false)

当然也可以使用类似于 .gitignore 的方式,定义排斥的目录名来实现。

二、写文件

写文件逻辑比较繁琐,需要先读取资源文件和清单文件的内容提取后再合并写出。

    aidl/ assets/ java/ 等目录下的文件直接复制,不存在重复不会有冲突

    res/values/ 下同名文件(strings、colors、styles等)内容合并

    AndroidManifest 合并

    合并权限,过滤掉重复权限合并 标签下内容,如:“meta-data”, “activity”, “service”, “receiver”, “provider”将以 . 开头的相对 name 替换成绝对路径
    如:android:name=".ui.activity.PlayerActivity" 改成 android:name="com.xxx.ui.activity.PlayerActivity"

    build.gradle 合并

    解析 android 节点下配置解析 dependencies 节点下依赖去除重复

    用正则表达式匹配,生成结果不是很准确,仅用于最后参考对比。

三、遇到的问题

    统一导包、R、BuildConfig

    由于这两个类是自动生成跟随库的包名的,每个库对应一组。合并工程后只剩下一组,之前在代码中引入的这两个文件包名现在无效。

    代码中使用正则表达式进行替换,例如:

    "import com\.[a-zA-Z_0-9.]*?\.R;" to "import $packageName.R;"
    
四、补充 DataBinding 的替换

在开发应用时为开发方便实用了 databinding 功能,打包后由于要移植到一个老的项目中,而那个项目的 gradle 版本还是 2.10,如果更新到 SDK 实用的 4.1 版本又会带来很多麻烦。不修改 2.10 生成目录是在应用包名下,导致 SDK 中的引用找不到生成后的 DataBinding。自己代码中虽然用到了 databinding,不过只停留在用 findViewbyId() 的功能上,想到这里就决定按照它的格式自己生成一个壳,移除 databinding 来兼容不同版本。

代码实现方式

    通过读取 layout 文件,生成 findViewbyId() 功能的代码

    layout/ 目录下的文件以 标签开头的就是 databinding 文件读取文件,匹配包含 id 的标签,并生成代码

    移除文件中的 标签,转移域名到下一级根目录

    替换导包 ViewDataBinding 、 DataBindingUtil

示例代码结构:

创建与 databinding 一样的类名和函数,用于移花接木的壳:

public interface ViewDataBinding {

    View getRoot();
}

public class DataBindingUtil {

    public static  SV inflate(LayoutInflater layoutInflater, int layoutId, Object o, boolean b) {
        if (layoutId == R.layout.activity_base) {
            return (SV) new ActivitybaseBinding(layoutInflater, layoutId);
        }
        return null;
    }
}

自动生成 findViewById 功能的代码,成员函数命名与 databinding 一致:

public class ActivitybaseBinding implements ViewDataBinding {

    private final View mRootView;
    public final android.support.v7.widget.Toolbar toolBar;

    public ActivitybaseBinding(LayoutInflater layoutInflater, int layoutId) {
        mRootView = layoutInflater.inflate(layoutId, null);
        toolBar = (android.support.v7.widget.Toolbar) mRootView.findViewById(R.id.tool_bar);
    }

    @Override
    public View getRoot() {
        return mRootView;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770013.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号