前言
在开发 Flutter 的 Android 插件时,你是否也遇到过这样的烦恼:在 Android Studio 中打开项目后,总是提示找不到 import io.flutter.xxx
包?虽然我们可以通过创建一个 resolve_flutter_depends.gradle
文件来解决这个问题,并在 build.gradle
中引用它,但这种方式比较笨拙,需要每个项目手动设置,非常不便。
实际上,我们可以利用 Gradle 插件来实现 Flutter 依赖的自动化配置,减少重复操作,提高开发效率。本文将介绍如何创建一个 Gradle 插件并发布到Maven仓库, 用于自动解决 Flutter Android 插件开发中的依赖问题。
创建 Gradle 插件
首先,我们来创建一个 Gradle 插件工程:
shell
mkdir gradle_plugin_flutter_depends
cd gradle_plugin_flutter_depends
gradle init
在 gradle init
过程中,可以选择项目类型为 library。其它的看你自己的需要选择, 下图是我的选择:
插件项目
在项目的 build.gradle
文件中进行如下配置:
gradle
plugins {
id 'java-library'
id 'java-gradle-plugin' // 添加 Gradle 组件
}
apply from: 'maven-push.gradle' // 插件发布配置,后面会讲到
repositories {
mavenCentral()
google()
}
dependencies {
// Gradle 相关 API
implementation gradleApi()
implementation localGroovy()
}
gradlePlugin {
plugins {
create("FlutterGradle") { // 插件名称
id = "pharos.flutter.dependencies" // 插件 ID
implementationClass = "com.e.g.flutter_gradle.FlutterDependenciesPluginPlugin" // 插件实现类
}
}
}
实现 Flutter 依赖插件功能
接下来,我们编写插件的功能实现类:
java
package com.e.g.flutter_gradle;
import org.gradle.api.Project;
import org.gradle.api.Plugin;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Properties;
public class FlutterDependenciesPluginPlugin implements Plugin<Project> {
public void apply(Project project) {
// 加载 local.properties 文件
Properties localProperties = new Properties();
File localPropertiesFile = project.getRootProject().file("local.properties");
if (localPropertiesFile.exists()) {
try (FileInputStream fis = new FileInputStream(localPropertiesFile)) {
localProperties.load(fis);
} catch (IOException e) {
throw new RuntimeException("Failed to load local.properties file", e);
}
}
// 获取 Flutter SDK 路径
String flutterRootPath = localProperties.getProperty("flutter.sdk");
if (flutterRootPath == null) {
throw new IllegalStateException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.");
}
String[] storageUrl = {System.getenv("FLUTTER_STORAGE_BASE_URL")};
if (storageUrl[0] == null) {
storageUrl[0] = "https://storage.flutter-io.cn";
}
// 配置仓库
RepositoryHandler repositories = project.getRepositories();
repositories.google();
repositories.mavenCentral();
repositories.maven(repo -> repo.setUrl(storageUrl[0] + "/download.flutter.io"));
// 获取引擎版本
File engineVersionFile = Paths.get(flutterRootPath, "bin", "internal", "engine.version").toFile();
String engineVersion;
try {
engineVersion = new String(java.nio.file.Files.readAllBytes(engineVersionFile.toPath())).trim();
} catch (IOException e) {
throw new RuntimeException("Failed to read engine version", e);
}
// 添加依赖
project.afterEvaluate(evaluatedProject -> {
if (evaluatedProject.getConfigurations().findByName("releaseImplementation") != null) {
evaluatedProject.getDependencies().add("releaseImplementation", "io.flutter:flutter_embedding_release:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("releaseImplementation", "io.flutter:armeabi_v7a_release:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("releaseImplementation", "io.flutter:arm64_v8a_release:1.0.0-" + engineVersion);
}
if (evaluatedProject.getConfigurations().findByName("debugImplementation") != null) {
evaluatedProject.getDependencies().add("debugImplementation", "io.flutter:flutter_embedding_profile:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("debugImplementation", "io.flutter:armeabi_v7a_profile:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("debugImplementation", "io.flutter:arm64_v8a_profile:1.0.0-" + engineVersion);
}
evaluatedProject.getDependencies().add("compileOnly", "io.flutter:flutter_embedding_debug:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("compileOnly", "io.flutter:armeabi_v7a_debug:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("compileOnly", "io.flutter:arm64_v8a_debug:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("compileOnly", "io.flutter:x86_debug:1.0.0-" + engineVersion);
evaluatedProject.getDependencies().add("compileOnly", "io.flutter:x86_64_debug:1.0.0-" + engineVersion);
});
}
}
发布到 Maven 仓库
使用 maven-publish
插件发布插件到 Maven 仓库:
gradle
# 必须添加此插件 才能发布 Maven
apply plugin: 'maven-publish'
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('gradle.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
afterEvaluate {
publishing {
repositories {
maven {
name = 'fooRelease'
allowInsecureProtocol = true
url = localProperties.getProperty('mvn.url.release')
credentials {
username = localProperties.getProperty('mvn.username')
password = localProperties.getProperty('mvn.password')
}
}
}
publications {
release(MavenPublication) {
groupId = localProperties.getProperty('mvn.groupid')
artifactId = 'flutter-dependencies'
version = "0.0.2"
afterEvaluate { artifact(tasks.getByName("jar")) }
}
}
}
}
执行以下命令发布插件:
shell
./gradlew publishReleasePublicationToFooReleaseRepository
在项目中使用插件
在 Flutter 插件项目的 android/build.gradle
中引入发布的插件:
gradle
buildscript {
repositories {
# 添加你的Maven仓库地址
maven {
url 'https://nexus.foo.com/repository/foo-moblie-central'
content {
includeGroup 'com.foo.flutter_gradle'
}
}
google(){
content {
excludeGroup 'com.foo.flutter_gradle'
}
}
mavenCentral(){
content {
excludeGroup 'com.foo.flutter_gradle'
}
}
}
dependencies {
# 添加你的插件依赖
classpath 'com.foo.flutter_gradle:flutter-dependencies:0.0.1'
classpath 'com.android.tools.build:gradle:7.3.0'
}
}
# 你的插件
apply plugin: 'pharos.flutter.dependencies'
在 local.properties
文件中配置 Flutter SDK 路径:
properties
sdk.dir=/Users/<USERNAME>/Library/Android/sdk
flutter.sdk=/Users/<USERNAME>/fvm/versions/custom_3.22.0-ohos
总结
通过创建 Gradle 插件,可以有效地简化 Flutter Android 插件开发中的 Flutter 依赖配置工作,避免了每次手动配置的繁琐操作,提高了开发效率和代码可维护性。希望本文能对你有所帮助,欢迎在开发中尝试这一方法。