使用 Gradle 插件优化 Flutter Android 插件开发中的 Flutter 依赖缺失问题

前言

在开发 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 依赖配置工作,避免了每次手动配置的繁琐操作,提高了开发效率和代码可维护性。希望本文能对你有所帮助,欢迎在开发中尝试这一方法。

撰写不易,请给个赞👍吧

相关推荐
帅次2 小时前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
枯骨成佛3 小时前
Android中Crash Debug技巧
android
sunly_5 小时前
Flutter:父组件,向子组件传值,子组件向二级页面传值
flutter
kim56598 小时前
android studio 更改gradle版本方法(备忘)
android·ide·gradle·android studio
咸芝麻鱼8 小时前
Android Studio | 最新版本配置要求高,JDK运行环境不适配,导致无法启动App
android·ide·android studio
无所谓จุ๊บ8 小时前
Android Studio使用c++编写
android·c++
csucoderlee9 小时前
Android Studio的新界面New UI,怎么切换回老界面
android·ui·android studio
kim56599 小时前
各版本android studio下载地址
android·ide·android studio
饮啦冰美式9 小时前
Android Studio 将项目打包成apk文件
android·ide·android studio
爱学习的绿叶9 小时前
flutter TabBarView 动态添加删除页面
flutter