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

撰写不易,请给个赞👍吧

相关推荐
小白球滚芝麻1 小时前
Unity下载文件断点续下
android·unity·c#·游戏引擎·vr
五味香2 小时前
Java学习,反射
android·java·开发语言·python·学习·flutter·kotlin
无极程序员2 小时前
PHP 魔术常量
android·java·开发语言·ide·php
weixin_449310842 小时前
高效集成:将聚水潭数据导入MySQL的实战案例
android·数据库·mysql
收银系统源码那点事4 小时前
零售餐饮收银台源码
flutter·uni-app·零售·收银系统源码·收银系统·连锁店收银系统
老杜_d4 小时前
Android studio 签名加固后的apk文件
android·ide·android studio
可遇_不可求5 小时前
ADB实战指南:解锁安卓设备的高级操作
android·adb
蹲街式等待5 小时前
Android Studio 右侧Gradle窗口只有test的task问题解决
android·ide·android studio
唯鹿6 小时前
Flutter如何适配RTL
android·flutter
Mis_wenwen6 小时前
flutter 解决webview加载重定向h5页面 返回重复加载问题
flutter·h5·webview·重定向