android - 如何从 android studio 中的自定义插件操作动态添加项目依赖项?

标签 android kotlin android-gradle-plugin android-studio-plugin

我需要为 Android studio 创建一个自定义插件,并且需要在 build.gradle 文件中添加依赖项。

通过 AnAction,我重写了 actionPerformed 方法。

现在我需要动态添加依赖项,在执行该操作后如何添加它?

最佳答案

我已经找到了解决方案并应用了相同的方法,

class GradleManager(private val project: Project) {

    companion object {
        const val DEFAULT_MODULE_NAME = "app"
        const val IMPLEMENTATION = "implementation"
        const val COMPILE = "compile"
        const val DEPENDENCIES = "dependencies"
    }

    private var buildGradle: Document? = null
    private var modules = arrayOf<Any>()
    private var projectBaseDir: VirtualFile? = null

    @Throws(FileNotFoundException::class)
    fun initBuildGradle(): Boolean {
        getModulesExist()
        val gradleVirtualFile: VirtualFile?
        gradleVirtualFile = if (modules.size > 1) {
            val isHaveAppModule: String? = modules.find { it == DEFAULT_MODULE_NAME } as String
            if (isHaveAppModule != null && isHaveAppModule != "") {
                projectBaseDir!!
                        .findChild(isHaveAppModule)!!
                        .findChild("build.gradle")
            } else {
                return false
            }
        } else {
            projectBaseDir!!
                    .findChild(modules[0] as String)!!
                    .findChild("build.gradle")
        }
        if (gradleVirtualFile != null) {
            buildGradle = FileDocumentManager.getInstance().getDocument(gradleVirtualFile)
        }
        return true
    }

    @Throws(FileNotFoundException::class)
    private fun getModulesExist() {
        val basePath = project.basePath
        if (StringUtils.isEmpty(basePath)) {
            throw FileNotFoundException("Project base path not found.")
        }
        projectBaseDir = LocalFileSystem.getInstance().findFileByPath(basePath!!)
        if (projectBaseDir == null) {
            throw FileNotFoundException("Project base directory not found.")
        }
        val virtualSettingsGradle = projectBaseDir!!.findChild("settings.gradle")
        if (virtualSettingsGradle != null) {
            val settingsGradle = FileDocumentManager.getInstance().getDocument(virtualSettingsGradle)
            if (settingsGradle != null) {
            modules = readSettingsGradle(settingsGradle)
        }
        } else if (projectBaseDir!!.findChild("build.gradle") == null) {
            throw FileNotFoundException("Project doesn't contain any gradle file.")
        }
    }

    fun addDependency(repository: String, actionEvent: AnActionEvent) {
        val documentText = buildGradle!!.text.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
        val sb = StringBuilder()
        var counter = 0
        var canSearch = false
        for (i in documentText.indices) {
            val line = documentText[i]
            if (canSearch) {
                if (line.contains("{")) {
                    counter += 1
                }
                if (line.contains("}")) {
                    if (counter > 0) {
                        counter -= 1
                    } else {
                        canSearch = false
                        sb.append("\t$repository").append("\n")
                    }
                }
            }
            if (line.contains(DEPENDENCIES)) {
                val tempLine = line.replace(DEPENDENCIES, "")
                if (tempLine.trim().equals("{", true)) {
                    canSearch = true
                } else {
                    if (!tempLine.trim().isRequiredField()) {
                        counter = -1
                        canSearch = true
                    } else {
                        if (tempLine.trim().contains("{")
                                && !tempLine.trim().contains("//")
                                && (tempLine.trim().contains(IMPLEMENTATION) || tempLine.trim().contains(COMPILE))
                        ) {
                            canSearch = true
                        }
                    }
                }
            }
            sb.append(line).append("\n")
        }
        writeToGradle(sb, actionEvent)
    }

    private fun writeToGradle(stringBuilder: StringBuilder, actionEvent: AnActionEvent) {
        val application = ApplicationManager.getApplication()
        application.invokeLater {
            application.runWriteAction { buildGradle!!.setText(stringBuilder) }
            syncProject(actionEvent)
        }
    }

    private fun syncProject(actionEvent: AnActionEvent) {
        val androidSyncAction = getAction("Android.SyncProject")
        val refreshAllProjectAction = getAction("ExternalSystem.RefreshAllProjects")
        if (androidSyncAction != null && androidSyncAction !is EmptyAction) {
            androidSyncAction.actionPerformed(actionEvent)
        } else if (refreshAllProjectAction != null && refreshAllProjectAction !is EmptyAction) {
            refreshAllProjectAction.actionPerformed(actionEvent)
        } else {
            SwingUtilities.invokeLater {
                Messages.showInfoMessage(
                        "Project sync failed.",
                        "SYNC FAILED"
                )
            }
        }
    }

    private fun getAction(actionId: String): AnAction? {
        return ActionManager.getInstance().getAction(actionId)
    }

    private fun readSettingsGradle(settingsGradle: Document): Array<Any> {
        return Stream.of(*settingsGradle.text.split("'".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
                .filter { s -> s.startsWith(":") }
                .map { s -> s.replace(":", "") }
                .toArray()
    }

    private fun String?.isRequiredField(): Boolean {
        return this != null && isNotEmpty() && isNotBlank()
    }
}

请引用here供引用。

关于android - 如何从 android studio 中的自定义插件操作动态添加项目依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57620509/

相关文章:

Java ProcessBuilder 不写换行符

android - Android Studio 中build.gradle 是如何自动改变的?

java - Kotlin 中的包等效可见性修饰符

arrays - 如何在Kotlin中将String转换为String数组?

java - 转换 SQLite 查询日期格式

android - 我怎样才能实现条形图

android-studio - Android Studio 中的代码覆盖率

android - Proguard 混淆整个包但仅一个文件

android - Android中推送通知的困惑

android - cursor.setNotificationUri() 和 getContentResolver().notifyChange(uri,null) 之间的区别