Skip to content

Instantly share code, notes, and snippets.

@Krosxx
Created March 11, 2021 10:55
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save Krosxx/cc0779d97d0cc807c53c4f847802dbf8 to your computer and use it in GitHub Desktop.
Save Krosxx/cc0779d97d0cc807c53c4f847802dbf8 to your computer and use it in GitHub Desktop.
Flutter module upload aar to maven
// This script is used to initialize the build in a module or plugin project.
// During this phase, the script applies the Maven plugin and configures the
// destination of the local repository.
// The local repository will contain the AAR and POM files.
void configureProject(Project project, String mavenUrl, String mavenUser, String mavenPwd, String version) {
if (!project.hasProperty("android")) {
throw new GradleException("Android property not found.")
}
if (!project.android.hasProperty("libraryVariants")) {
throw new GradleException("Can't generate AAR on a non Android library project.")
}
project.apply plugin: "maven"
// Snapshot versions include the timestamp in the artifact name.
// Therefore, remove the snapshot part, so new runs of `flutter build aar` overrides existing artifacts.
// This version isn't relevant in Flutter since the pub version is used
// to resolve dependencies.
project.version = version
if (mavenUrl.startsWith("file:")) {
//本地路径时,原逻辑
project.version = project.version.replace("-SNAPSHOT", "")
}
project.android.libraryVariants.all { variant ->
addAarTask(project, variant)
}
project.uploadArchives {
repositories {
mavenDeployer {
repository(url: mavenUrl) {
if (mavenUser != null) {
authentication(userName: mavenUser, password: mavenPwd)
}
}
//默认本地路径:
//repository(url: "file://${outputDir}/outputs/repo")
}
}
}
if (!project.property("is-plugin").toBoolean()) {
return
}
if (project.hasProperty('localEngineOut')) {
// TODO(egarciad): Support local engine.
// This most likely requires refactoring `flutter.gradle`, so the logic can be reused.
throw new GradleException(
"Local engine isn't supported when building the plugins as AAR. " +
"See: https://github.com/flutter/flutter/issues/40866")
}
// This is a Flutter plugin project. Plugin projects don't apply the Flutter Gradle plugin,
// as a result, add the dependency on the embedding.
project.repositories {
maven {
url "https://storage.googleapis.com/download.flutter.io"
}
}
String engineVersion = flutterEngineVersion()
project.dependencies {
// Add the embedding dependency.
//使用api方式打入aar
compileOnly("io.flutter:flutter_embedding_release:1.0.0-$engineVersion") {
// api("io.flutter:flutter_embedding_release:1.0.0-$engineVersion") {
// We only need to expose io.flutter.plugin.*
// No need for the embedding transitive dependencies.
transitive = true
}
}
}
void configurePlugin(Project project, String outputDir, String mavenUser, String mavenPwd) {
if (!project.hasProperty("android")) {
// A plugin doesn't support the Android platform when this property isn't defined in the plugin.
return
}
//flutter plugin 版本号
File pubspecFile = project.file("../pubspec.yaml")
String versionLine = pubspecFile.readLines().find { line->
line.startsWith("version:")
}
def pluginVersion = versionLine.split(":")[1].trim()
println("configurePlugin: " + project.toString() + " v" + pluginVersion)
configureProject(project, outputDir, mavenUser, mavenPwd, pluginVersion)
}
void addAarTask(Project project, variant) {
String variantName = variant.name.capitalize()
String taskName = "assembleAar$variantName"
project.tasks.create(name: taskName) {
// This check is required to be able to configure the archives before `uploadArchives` runs.
if (!project.gradle.startParameter.taskNames.contains(taskName)) {
return
}
project.uploadArchives.repositories.mavenDeployer {
pom {
artifactId = "${project.name}_${variant.name.toLowerCase()}"
}
}
overrideDefaultPublishConfig(project, variant)
// Generate the Maven artifacts.
finalizedBy "uploadArchives"
}
}
// This method mimics the logic in AGP when `android.defaultPublishConfig` is set in `build.gradle`:
// https://android.googlesource.com/platform/tools/base/+/studio-master-dev/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/VariantHelper.java
//
// Unfortunately, `android.defaultPublishConfig` cannot be overriden at this point since
// AGP already run this code.
void overrideDefaultPublishConfig(Project project, variant) {
String variantName = variant.name.capitalize()
Task bundle = project.tasks.findByName("bundle${variantName}Aar")
// gradle:3.2.0
if (bundle == null) {
bundle = project.tasks.findByName("bundle${variantName}") // gradle:3.1.0
}
if (bundle == null) {
throw new GradleException("Can't generate AAR for variant ${variantName}.")
}
// Clear the current archive artifacts since the artifacts are based on `android.defaultPublishConfig`.
project.configurations["archives"].artifacts.clear()
// Add the artifact that will be published.
project.artifacts.add("archives", bundle)
def scopeMappings = project.uploadArchives.repositories.mavenDeployer.pom.scopeMappings
// Clear the scope mappings added by AGP since they are based on the current `android.defaultPublishConfig`.
scopeMappings.mappings.clear()
// Add the new mappings.
for (Configuration configuration : flattenConfiguration(variant.runtimeConfiguration)) {
scopeMappings.addMapping(/* priority = */ 300, configuration, "compile")
}
}
Set<Configuration> flattenConfiguration(Configuration configuration) {
Set<Configuration> configs = [configuration]
for (Configuration extend : configuration.extendsFrom) {
configs.addAll(flattenConfiguration(extend))
}
return configs
}
projectsEvaluated {
assert rootProject.hasProperty("is-plugin")
if (rootProject.property("is-plugin").toBoolean()) {
assert rootProject.hasProperty("maven-url")
// In plugin projects, the root project is the plugin.
configureProject(rootProject, rootProject.property("maven-url"),
rootProject.property("maven-user"), rootProject.property("maven-pwd"),
project.property("buildNumber")
)
return
}
// The module project is the `:flutter` subproject.
Project moduleProject = rootProject.subprojects.find { it.name == "flutter" }
assert moduleProject != null
assert moduleProject.hasProperty("maven-url")
configureProject(moduleProject, moduleProject.property("maven-url"),
moduleProject.property("maven-user"), moduleProject.property("maven-pwd"),
moduleProject.property("buildNumber")
)
// Gets the plugin subprojects.
Set<Project> modulePlugins = rootProject.subprojects.findAll {
it.name != "flutter" && it.name != "app"
}
// When a module is built as a Maven artifacts, plugins must also be built this way
// because the module POM's file will include a dependency on the plugin Maven artifact.
// This is due to the Android Gradle Plugin expecting all library subprojects to be published
// as Maven artifacts.
String mavenUrl = moduleProject.property("maven-url")
String version = moduleProject.property("buildNumber")
println("Version: $version")
println("MavenUrl: " + mavenUrl)
//输出 配置
String buildMode = moduleProject.gradle.startParameter
.taskNames.find { it.startsWith("assembleAar") }.substring(11)
println("BuildMode: $buildMode")
println("================================================================================")
//配置插件
modulePlugins.each { pluginProject ->
configurePlugin(pluginProject, mavenUrl,
moduleProject.property("maven-user"), moduleProject.property("maven-pwd"))
moduleProject.android.libraryVariants.all { variant ->
// Configure the `assembleAar<variantName>` task for each plugin's projects and make
// the module's equivalent task depend on the plugin's task.
String variantName = variant.name.capitalize()
moduleProject.tasks.findByPath("assembleAar$variantName")
.dependsOn(pluginProject.tasks.findByPath("assembleAar$variantName"))
}
}
//结束
println("================================================================================")
String mUrl = mavenUrl
if (mavenUrl.startsWith("file://")) {
mUrl = mavenUrl.substring(7)
}
String groupId = moduleProject.group
println("""
1. 添加maven地址
repositories {
maven {
url '${mUrl}'
}
maven {
url 'https://storage.googleapis.com/download.flutter.io'
}
}
2. 添加依赖
dependencies {
implementation '${groupId}:flutter_${buildMode.toLowerCase()}:${version}'
}
""")
}
@Krosxx
Copy link
Author

Krosxx commented Mar 11, 2021

Flutter Version: 2.x
Flutter 3.x 请看评论区

Usage:

in dir: ./script

create upload.sh:

#!/usr/bin/env sh

flutter pub get
cd ..
./gradlew build

cd .android

./gradlew \
  -I=../script/flutter_aar_upload.gradle \
  -Pmaven-url=http://your_maven_url \
  -Pmaven-user=admin \
  -Pmaven-pwd=admin123 \
  -Pis-plugin=false \
  -PbuildNumber=${pom-version} \
  -Ptarget-platform=android-arm,android-arm64,android-x64 assembleAarRelease

exec upload.sh

参数说明
-Pmaven-url 可以是本地路径,也可为远程地址
示例:
maven-url=file:///Users/xxx/StudioProjects/xxx/build/host
maven-url=http://192.168.1.100:8081/repository/maven-releases/

maven-user 与 maven-pwd 为maven远程用户及密码,若发布到本地无需设置

-PbuildNumber=1.0.0 为版本号

最后 assembleAarRelease 为打包类型,assembleAarDebug, assembleAarProfile

@viniciuslvidal
Copy link

viniciuslvidal commented Dec 14, 2021

Hello. Thank you very much for share the script, it works fine for flutter (release, profile, debug). I made a pipeline in Azure DevOps using it.

Please I have a question: It's possible to build updated dependencies together with flutter in automatic form? In our case we put "only if" condition and setted "flutter" in project.name, and when need to update dependencies (example: url_launcher) we replace for this, but if we keep we have error 409 on the second run. (because artifact already exists in repo).

Question-script

Regards

@Krosxx
Copy link
Author

Krosxx commented Jan 5, 2022

maven repo server should enable allow redeploy

refer: https://blog.csdn.net/ziwuzhulin/article/details/103375454

@ahmdmau
Copy link

ahmdmau commented Jun 9, 2022

Hi, thank you so much for sharing this script. I have one question, Can i deploy the flutter aar into jfrog artifactory with this script? Thanks.

@Krosxx
Copy link
Author

Krosxx commented Jun 9, 2022

Hi, thank you so much for sharing this script. I have one question, Can i deploy the flutter aar into jfrog artifactory with this script? Thanks.

@ahmdmau I have no idea, but you can refer https://jfrog.com/knowledge-base/how-to-publish-build-info-and-artifacts-from-a-gradle-android-project-into-artifactory/ to modify this script.

@xymelon
Copy link

xymelon commented Dec 2, 2022

./gradlew build确实找不到,应该是先进入.android目录吧?

目录格式如下:
image

@Krosxx
Copy link
Author

Krosxx commented Dec 2, 2022

@xymelon 第一条评论有 cd .android 这个步骤的

@xiejianchao
Copy link

Hi Vove7,在 flutter 3.3.9 和 3.4.0-38.pre1 上这个脚本已经不能工作。
直接执行脚本编译成功后会出现如下错误:
image

flutter_aar_upload.gradle 中第14行由 project.apply plugin: "maven"修改为 project.apply plugin: "maven-publish" 后,编译成功后又会出现如下错误:
image

请教下该如何修改呢?

@xymelon
Copy link

xymelon commented Dec 3, 2022

@xymelon 第一条评论有 cd .android 这个步骤的

感谢回复,看第一条评论的脚本,是先进入的上层目录cd ..,再执行的./gradlew build,上层目录中找不到./gradlew,导致出错。
然后再问下,执行./gradlew build目的在哪?

#!/usr/bin/env sh

flutter pub get
cd ..
./gradlew build

cd .android

@Krosxx
Copy link
Author

Krosxx commented Dec 3, 2022

@xiejianchao
可以参考下这篇博客,按照之前版本思路来适配新版flutter gradle,当时flutter版本好像是2.x
https://blog.csdn.net/qq_37299249/article/details/115012889

@xiejianchao
Copy link

xiejianchao commented Dec 4, 2022

感谢回复和提供思路,我基于最新的 flutter 3.3.9 stable 版的 aar_init_script.gradle 文件做了修改,实测可以上传到远程私有仓库,如果有遇到这个问题的朋友可以参考下。
flutter_aar_build_upload.gradle

@wqandroid
Copy link

image

@paolorotolo
Copy link

@wqandroid make sure you're passing is-plugin as parameter when you run your script

@JKE7-supplier
Copy link

感谢两位 @Vove7 @xiejianchao提供的Flutter Version: 2.x and 3.x,我已经成功使用 3.x flutter_aar_build_upload.gradle上传到本地的nexus了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment