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

撰写不易,请给个赞👍吧

相关推荐
xiaoshiquan12063 分钟前
Android Studio里,SDK Manager显示不全问题
android·ide·android studio
Lstone73641 小时前
Bitmap深入分析(一)
android
一起搞IT吧1 小时前
Android功耗系列专题理论之十四:Sensor功耗问题分析方法
android·c++·智能手机·性能优化
ByNotD0g2 小时前
Doris 学习笔记
android·笔记·学习
修炼者2 小时前
【Android进阶】 RenderEffect的底层实现
android
bropro3 小时前
MySQL不使用子查询的原因
android·数据库·mysql
执笔论英雄3 小时前
【cuda】 pinpaged
android·java·数据库
新青年.4 小时前
Android(Compose)使用 LibVLC 播放 RTSP 视频流
android
Trust yourself2434 小时前
Flutter开发中遇到下载Flutter SDK速度缓慢问题
flutter