考虑android library+flutter module怎么生成aar

简单介绍

开始学习flutter之后比较关注的实际问题之一就是怎么混合开发,今天主要思考一下Android项目中native(android library)+flutter以什么形式进行混合开发以及怎么生成aar的问题。以下的总结是我的拙见,在这里也是想确认大家是否也遇到了相同的问题,有不对的欢迎批评指教~~

大致的混合开发形式以及遇到的问题为:

1、使用官方的flutter module形式,依据官方给出的集成方案Add Flutter to existing apps

该方案中当native项目为android library时打包aar可能会存在一些问题。由于android library打包成的aar并不会包含其依赖的aar或module的内容,所以此时native项目生成的aar并不会包含flutter module中的内容,flutter module需要单独再打一个aar出来给调用方。

2、方案1存在的问题为aar文件本身不包含依赖传递的信息,很简单想到借助于maven pom传递依赖,即形成第2种方案;flutter module项目单独生成aar,上传至maven远程或本地仓库,在android library项目中通过仓库获取该aar,同样android library生成的aar也会上传到仓库,调用方通过仓库获取,所有依赖关系都会跟随pom文件进行传递。

该方案可能存在的问题为: 1)官方推荐的flutter module的目录结构为.android、.ios、lib,而且其中.android和.ios目录在.gitignore中,即不推荐上传module中的native项目(其他人从git clone该项目之后,通过执行flutter packages get即可自动生成.android、.ios目录),则不推荐在.android中添加业务代码或者自定义操作,那么就不方便执行flutter module的aar自动生成以及上传; 2)android library通过aar依赖flutter module不便于开发时的测试。

3、第三种方案为不使用官方推荐的flutter module形式,将dart代码,native项目组合为一个工程,类似于Flutter Application结构,只是native项目不是com.android.application,而是com.android.library。

该方案不存在flutter module怎么被依赖的问题,只需要在android library项目中生成aar即可。

选择方案

个人理解看下来可能第3种方案比较方便,但是如果想使用官方flutter module形式且开发方便,倾向于选择第一种方案:即通过官方集成方案将android library依赖于flutter module。

所以需要试图解决方案1存在的问题,实现android library项目生成的aar能包含其依赖的flutter module的内容。

解决问题

一开始解决问题的目标定为合并多个aar,github上也有生成fat-aar的解决方案。但是由于目前flutter module只包含自动生成的android原生代码,没有资源文件(如下第一张图),并且flutter module生成的aar(结构如下第二张图)中比较重要的几部分为asssets、libs、jni、classes.jar,所以可以预想将问题简化为:android library项目生成的aar只需要包含上面这几部分或许就ok了,先忽略manifest、res等的合并。

确定了解决方案之后,就开始分以下几点开始试验:

1、集成flutter module的assets

从flutter.gradle文件中可得知,assets目录中内容的生成主要依靠task依赖执行:


 Task mergeAssets = project.tasks.findByPath(":${mainModuleName}:merge${variant.name.capitalize()}Assets")
if (mergeAssets){                 
 mergeAssets.dependsOn(copyFlutterAssetsTask)
}
复制代码

其中copyFlutterAssetsTask还会依赖于其他flutter task,执行flutter build操作;所需要的assets文件最后都会被放入build/intermediates/library_assets/${buildType}/package${buildTypeCapitalize()}Assets/out目录中,其中buildType即为debug或者release或其他。

所以为了合并assets需要完成如下两件事情:

1)在android library中执行assemble操作时需要能执行flutter module的copyFlutterAssetsTask任务; 解决方案为在android library的build.gradle中添加如下内容:

def flutterProject = project.rootProject.findProject(":flutter")

    flutterProject.afterEvaluate {
        flutterProject.android.libraryVariants.all {
            variant ->
                if (variant.name == 'debug' || variant.name == 'release') {
                    project.tasks.findByName("package${variant.name.capitalize()}Assets").dependsOn flutterProject.tasks.findByName("copyFlutterAssets${variant.name.capitalize()}")
                }
        }
    }
复制代码

同时要在android library的root project的build.gradle中添加如下配置,其中'mylibrary'为android library的module name;目前不是很清楚不增加为什么无法执行上面配置的flutterProject.afterEvaluate,所以这一点还需要优化:

ext { mainModuleName = 'mylibrary' }

复制代码

2)需要能将上面flutter module的assets out目录添加为android library的assets目录;

if (variant.name == 'release') {
android.sourceSets.release.assets.srcDirs += flutterProject.getBuildDir().getAbsolutePath() + "/intermediates/library_assets/${variant.name}/package${variant.name.capitalize()}Assets/out"
} else if (variant.name == 'debug') {
android.sourceSets.debug.assets.srcDirs += flutterProject.getBuildDir().getAbsolutePath() + "/intermediates/library_assets/${variant.name}/package${variant.name.capitalize()}Assets/out"
}
复制代码

2、集成flutter module的libs和jni

flutter.gradle中的task会将flutter sdk中的flutter.jar以及相关的so文件自动添加为flutter module的依赖,具体内容如下:

private void addFlutterJarApiDependency(Project project, buildType, Task flutterX86JarTask) {
        project.dependencies {
            String configuration;
            if (project.getConfigurations().findByName("api")) {
                configuration = buildType.name + "Api";
            } else {
                configuration = buildType.name + "Compile";
            }
            add(configuration, project.files {
                String buildMode = buildModeFor(buildType)
                if (buildMode == "debug") {
                    [flutterX86JarTask, debugFlutterJar]
                } else if (buildMode == "profile") {
                    profileFlutterJar
                } else if (buildMode == "dynamicProfile") {
                    dynamicProfileFlutterJar
                } else if (buildMode == "dynamicRelease") {
                    dynamicReleaseFlutterJar
                } else {
                    releaseFlutterJar
                }
            })
        }
    }
复制代码

这一点的解决方案即为将这些依赖添加为android library的依赖,具体做法为在android library的build.gradle中添加如下内容:

flutterProject.configurations.each {
            conf ->
                conf.getDependencies().each {
                    dep ->
                        if (dep instanceof org.gradle.api.artifacts.FileCollectionDependency) {
                            org.gradle.api.file.FileCollection fileCollection = dep.getFiles().filter { file -> file.getName().contains("flutter") }
                            if (!fileCollection.isEmpty()) {
                                if (project.configurations.contains(conf)) {
                                    project.dependencies { add(conf.getName(), dep) }
                                }
                            }
                        }
                }
        }
复制代码

3、集成classes.jar里面的内容

这一点也比较简单,因为flutter module里面java代码作为android library的源码,具体做法为

android.sourceSets.main.java.srcDirs += flutterProject.getProjectDir().getAbsolutePath() + "/src/main/java"

复制代码

经过以上几点的集成,android library中assembleRelease或者assembleDebug生成的aar就会包含flutter module中几大重要的内容,然后将此aar放在另一个android application中引用,也可以正常调起flutter module中的flutter页面,说明集成成功。当然如果以后flutter module在资源、manifest清单文件中有更多重要的内容,则需要考虑这些内容的合并,就会比较复杂。

目前的实现方案比较简单,希望大家一起讨论一下是否可选第1种方案进行混合开发、其存在的问题是否需要解决以及大家一般怎么解决(我不希望自己又走到了某种歪门邪道。。。)~~;当然如果本文的方案值得使用,后续还会继续进行优化。

转载于:https://juejin.im/post/5caecd4af265da038d0b30c7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 是谷歌开发的跨平台移动应用开发框架,它能够将 Dart 代码编译为本地平台的 ARM 代码,在 iOS 和 Android 平台上运行。Flutter 支持与原生代码混合使用,这使得开发人员可以使用 Flutter 开发 UI,同时使用原生代码处理一些高级功能。 如果你想将 Flutter 作为一个 aar 库嵌入到 Android 项目中,可以按照以下步骤: 1. 在 Flutter 项目中创建插件 Flutter 插件是一种将 Flutter 功能转换为原生代码的机制。插件包含了一个 Dart API 和一个原生 API,它们之间通过平台通道进行通信。要将 Flutter 项目作为 aar 库嵌入到 Android 项目中,你需要将 Flutter 插件创建为一个 aar 库。 你可以通过运行以下命令创建一个 Flutter 插件: ``` flutter create --template=plugin my_flutter_plugin ``` 这将创建一个名为 my_flutter_plugin 的插件,并在其中包含一个 Flutter 模块和一个 Android 模块。 2. 将 Flutter 插件打包为 aar 库 要将 Flutter 插件打包为 aar 库,你需要对 Android 模块进行一些修改。首先,将 Android 模块中的 build.gradle 文件中的 apply plugin 行更改为: ``` apply plugin: 'com.android.library' ``` 然后,将以下内容添加到 build.gradle 文件的末尾: ``` android { ... sourceSets { main.java.srcDirs += "${flutterRoot}/packages/flutter_module/src/main/java" } } task copyFlutterFramework(type: Copy) { from new File(project(':flutter').projectDir, 'build/app/outputs/flutter-apk/app-release-unsigned.apk') into('libs') { rename { 'app-release-unsigned.apk' } } } preBuild.dependsOn(copyFlutterFramework) ``` 这将允许你将 Flutter 模块中的 Dart 代码编译为本地平台的代码,并将其打包到 aar 文件中。 最后,在 Android 模块的 build.gradle 文件中添加以下依赖项: ``` dependencies { implementation 'com.google.android.material:material:1.0.0' implementation project(':flutter') } ``` 3. 将 aar 库添加到 Android 项目中 要将 aar 库添加到 Android 项目中,你需要将 aar 文件复制到 Android 项目的 libs 目录中,并将以下内容添加到 Android 项目的 build.gradle 文件中: ``` repositories { flatDir { dirs 'libs' } } dependencies { implementation(name:'my_flutter_plugin', ext:'aar') } ``` 这将允许 Android 项目在构建时引用 aar 库。 这些步骤将允许你将 Flutter 作为一个 aar 库嵌入到 Android 项目中。当你构建 Android 项目时,Flutter 将作为一个原生库被包含在内,可以通过平台通道与 Dart 代码进行通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值