Android Studio 4.1中的模板插件
Android Studio 4.1中的模板插件
来自:http://tommwq.tech/blog/2021/02/28/312
原文:https://steewsc.medium.com/template-plugin-for-android-studio-4-1-92dcbc689d39
作者:Stevica Trajanovic
如果你在开发一个新项目,或者你想将旧项目迁移到新架构,你应该考虑建立一个模板,好省去编写样板代码的工作,把时间用到其他地方。
直到最近之前,要建立模板,只需要进入$ANDROID_STUDIO/plugins/android/lib/templates/文件夹寻找示例。但从Android Studio 4.1开始,这种方法不再奏效。就在我编写完模板,并想要升级Android Studio的时候,我才意识到这一点。
当然也有好的一面。现在你可以用Kotlin替代FTL,同时,模板也被JetBrains IntelliJ平台插件所替代。
首先打开 https://github.com/JetBrains/intellij-platform-plugin-template ,按照README的说明操作。(脱水版:点击“Use this template”绿色按钮)
按照向导指示执行完毕,你会得到一个代码仓库,用来保存插件代码。现在你需要通过克隆或下载来得到代码。
接着用Android Studio打开插件代码。现在可以做一些调整,让插件代码适配你的Android Studio版本。
请记住:我在这里使用某些类和包的名字只是作为参考,你可以放心的修改。
1 重新组织包
对于这个例子,我将自动生成的类移动到了我的基础包com.github.steewsc.mvisetup。
2 gradle.properties
对于gradle.properties文件,你要设置
- pluginName。设置为mvi-setup。
- pluginGroup。设置为com.github.steewsc.mvisetup。
- platformVersion。设置为你使用的Android Studio的平台版本。比如对于Android Studio 4.1、4.2 Canary 14可以设置为2020.2。更多版本信息可以查看 https://jetbrains.org/intellij/sdk/docs/products/android_studio.html#matching-versions-of-the-intellij-platform-with-the-android-studio-version 。
- platformPlugins。设置为
java, com.intellij.java, org.jetbrains.android, android, org.jetbrains.kotlin
。
3 plugin.xml
接下来在src/main/resources/META-INF目录下打开plugin.xml文件并设置:
- id。设置为com.github.steewsc.mvisetup(即gradle.properties中的pluginGroup)。
- name。设置为mvi-setup(即gradle.properties中的pluginName)。
- vendor。设置为steewsc。
然后增加3个依赖项(依赖项com.intellij.modules.platform应该已经自动添加)
- org.jetbrains.android
- org.jetbrains.kotlin
- com.intellij.modules.java
在所有部分中,将基础包名称设置为com.github.steewsc.mvisetup。
4 settings.gradle.kts
设置rootProject.name为mvi-setup(或你的插件的名字)。
执行gradle同步,这样我们就完成设置部分,可以开始编码。
为了让模板在菜单中可见,我们必须:
- 从WizardTemplateProvider派生类
- Template
- Recipe
- 模板文件
这里有些类似于我们在Android Studio 4.1之前需要做的工作,除了现在使用的是Kotlin。实际上我使用了旧模板(基于FTL)作为新插件的源代码。
我在编写插件时遇到一个问题。因为我在RecipeExecutor中使用了Project实例,不得不使用一些不好的编码技巧(我想尽快完成工作),直到我找到更合适的办法。
更新MyProjectManagerListener.kt来存储Project对象:
package com.github.steewsc.mvisetup.listeners
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManagerListener
import com.github.steewsc.mvisetup.services.MyProjectService
class MyProjectManagerListener : ProjectManagerListener {
override fun projectOpened(project: Project) {
projectInstance = project
project.getService(MyProjectService::class.java)
}
override fun projectClosing(project: Project) {
projectInstance = <strong>null</strong>
super.projectClosing(project)
}
companion object {
var projectInstance: Project? = <strong>null</strong>
}
}
这里我忽略Java版本。在配置完成后,你可以很容易的用Java编写插件。
5 模板文件
ActivityAndLayout.kt
import com.android.tools.idea.wizard.template.ProjectTemplateData
import com.android.tools.idea.wizard.template.extractLetters
fun someActivity(
packageName: String,
entityName: String,
layoutName: String,
projectData: ProjectTemplateData
) = """
package $packageName
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import ${projectData.applicationPackage}.R;
class ${entityName}sActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.${extractLetters(layoutName.toLowerCase())})
}
}
"""
fun someActivityLayout(
packageName: String,
entityName: String) = """
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http:<em>//</em><em>schemas.android.com/apk/res/android"</em>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${packageName}.${entityName}sActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
"""
recipe.kt
package other.mviSetup
import com.android.tools.idea.wizard.template.ModuleTemplateData
import com.android.tools.idea.wizard.template.RecipeExecutor
import com.android.tools.idea.wizard.template.activityToLayout
import com.android.tools.idea.wizard.template.extractLetters
import com.android.tools.idea.wizard.template.impl.activities.common.addAllKotlinDependencies
import com.github.steewsc.mvisetup.listeners.MyProjectManagerListener.Companion.projectInstance
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.PsiManager
import someActivity
import someActivityLayout
fun RecipeExecutor.mviSetup(
moduleData: ModuleTemplateData,
packageName: String,
entityName: String,
layoutName: String
) {
val (projectData) = moduleData
val project = projectInstance ?: return
addAllKotlinDependencies(moduleData)
val virtualFiles = ProjectRootManager.getInstance(project).contentSourceRoots
val virtSrc = virtualFiles.first { it.path.contains("src") }
val virtRes = virtualFiles.first { it.path.contains("res") }
val directorySrc = PsiManager.getInstance(project).findDirectory(virtSrc)!!
val directoryRes = PsiManager.getInstance(project).findDirectory(virtRes)!!
someActivity(packageName, entityName, layoutName, projectData)
.save(directorySrc, packageName, "${entityName}sActivity.kt")
someActivityLayout(packageName, entityName)
.save(directoryRes, "layout", "${layoutName}.xml")
}
fun String.save(srcDir: PsiDirectory, subDirPath: String, fileName: String) {
try {
val destDir = subDirPath.split(".").toDir(srcDir)
val psiFile = PsiFileFactory
.getInstance(srcDir.project)
.createFileFromText(fileName, KotlinLanguage.INSTANCE, this)
destDir.add(psiFile)
}catch (exc: Exception) {
exc.printStackTrace()
}
}
fun List<String>.toDir(srcDir: PsiDirectory): PsiDirectory {
var result = srcDir
forEach {
result = result.findSubdirectory(it) ?: result.createSubdirectory(it)
}
return result
}
Template.kt
package other.mviSetup
import com.android.tools.idea.wizard.template.*
import java.io.File
import mviSetup
val mviSetupTemplate
get() = template {
revision = 2
name = "MY Setup with Activity"
description = "Creates a new activity along layout file."
minApi = 16
minBuildApi = 16
category = Category.Other <em>// </em><em>Check other categories</em>
formFactor = FormFactor.Mobile
screens = listOf(WizardUiContext.FragmentGallery, WizardUiContext.MenuEntry,
WizardUiContext.NewProject, WizardUiContext.NewModule)
val packageNameParam = defaultPackageNameParameter
val entityName = stringParameter {
name = "Entity Name"
default = "Wurst"
help = "The name of the entity class to create and use in Activity"
constraints = listOf(Constraint.NONEMPTY)
}
val layoutName = stringParameter {
name = "Layout Name"
default = "my_act"
help = "The name of the layout to create for the activity"
constraints = listOf(Constraint.LAYOUT, Constraint.UNIQUE, Constraint.NONEMPTY)
suggest = { "${activityToLayout(entityName.value.toLowerCase())}s" }
}
widgets(
TextFieldWidget(entityName),
TextFieldWidget(layoutName),
PackageNameWidget(packageNameParam)
)
recipe = { data: TemplateData ->
mviSetup(
data as ModuleTemplateData,
packageNameParam.value,
entityName.value,
layoutName.value
)
}
}
val defaultPackageNameParameter get() = stringParameter {
name = "Package name"
visible = { !isNewModule }
default = "com.mycompany.myapp"
constraints = listOf(Constraint.PACKAGE)
suggest = { packageName }
}
WizardTemplateProviderImpl.kt
package other
import com.android.tools.idea.wizard.template.Template
import com.android.tools.idea.wizard.template.WizardTemplateProvider
import other.mviSetup.mviSetupTemplate
class WizardTemplateProviderImpl : WizardTemplateProvider() {
override fun getTemplates(): List<Template> = listOf(mviSetupTemplate)
}
现在回到plugin.xml,添加你的导模板。
<extensions defaultExtensionNs="com.android.tools.idea.wizard.template">
<wizardTemplateProvider implementation="other.WizardTemplateProviderImpl" />
</extensions>
打开Gradle标签,运行buildPlugin。
如果一切正常,你将会看到插件已经被保存到YOUR_PROJECT_DIR\build\libs\my-setup-0.1.0.jar。
你可以将插件拖拽到Android Studio中,或者通过菜单Settings->Plugins->Install Plugin from Disk来安装插件jar。
重启IDE,尝试运行插件。右键点击项目中的某个包,在弹出菜单中依次选择New->Other->MY Setup with Activity,顺利的话你会看到向导屏幕。当你点击Next/Finish按钮,插件生成文件。
这只是一个基本Activity创建模板,你可以将它作为MVI或其他模式的基础样板,并让重构旧项目轻而易举。
Figure 14: 屏幕1:在新建菜单中点击MVI Setup with Fragment后
Figure 15: 屏幕2:“MVI Setup with Fragment”向导生成的文件(红色部分)
如果你遇到任何问题,你可以在idea.log文件中看到堆栈跟踪(Android Studio->Help->Show log In Explorer/Finder..)。
如果你在新建菜单中看不到Activity/Fragment和其他常见的子菜单,只需卸载插件(Settings->Plugins->YourPlugin->Uninstall),这些子菜单会在IDE重启后出现。检查idea.log中的错误,修复插件源代码,增加插件版本,构建并重新安装插件。
示例代码在https://github.com/steewsc/template。
Android Studio 4.1中的模板插件相关推荐
- 在 Android Studio 2.2 中愉快地使用 C/C++
2019独角兽企业重金招聘Python工程师标准>>> Android Studio 2.2 正式版发布后,看到更新内容中有提到对 C/C++ 支持的完善,表示非常高兴.然后将官网上 ...
- 如何在没有 USB 数据线的情况下使用 Android Studio 在手机中安装 Android
背景 如何在没有 USB 数据线的情况下使用 Android Studio 在手机中安装 Android 应用程序? 运行调式一个Android项目,写下必要的代码后,接下来的任务是在模拟器或手机上运 ...
- Android studio安装过程中入的坑的记录与记录
Android studio安装过程中入的坑的记录与记录 * 由于最近项目的需求,所以最近一直在配置安卓的开发环境,之前用的是Eclipse + ADT的模式开发的,配置环境也花了一些时间,但是由于谷 ...
- 解决Android Studio安装过程中“SDK tools directory is missing”的问题
解决Android Studio安装过程中"SDK tools directory is missing"的问题 参考文章: (1)解决Android Studio安装过程中&qu ...
- Android Studio使用过程中Java类突然报红,但项目可运行解决方案
Android Studio使用过程中Java类突然报红,但项目可运行解决方案 参考文章: (1)Android Studio使用过程中Java类突然报红,但项目可运行解决方案 (2)https:// ...
- Android Studio 3.0中mipmap-anydpi-v26是什么东东
在Android Studio 3.0中一旦我们创建了一个项目,一个名为mipmap-anydpi-v26自动创建的文件夹在res文件夹下.它究竟能干什么?为什么我们需要这个?我们在开发时该如何利用它 ...
- 【Android】Android Studio 1.5+ 中混合调试Native和Java代码
[Android]Android Studio 1.5+ 中调试Native和Java代码 Android Studio 1.5+表示Android Studio 1.5版本以及以上. 网上大部分中文 ...
- Android Studio 1.5+ 中调试Native和Java代码
Android Studio 1.5+ 中调试Native和Java代码 步骤如下 1.安装了1.5版+的Android Studio 2.安装LLDB:(LLDB是Low Level DeBugge ...
- android studio类似软件,使Android Studio更高效的几款插件推荐
Android Studio是一个非常强大的工具.它可以为多种不同的设备设计UI界面,使用起来非常灵活.我们可以在布局编辑器中拖放view和widget,并用xml对具体的细节进行定制编码.它在代码编 ...
- Android Studio安装过程中的常见问题
1.关于下载地址的问题 https://developer.android.google.cn/ https://www.androiddevtools.cn/ 2.关于版本的问题 与操作系统位数一致 ...
最新文章
- poj3216 Prime Path(BFS)
- 【qduoj - 纳新题】凑数题(恰好装满类0-1背包 或 母函数)
- 10个优秀视差滚动插件
- 泡泡玛特2021年营收44.9亿元 同比增长78.7%
- 银辉给园子里的兄弟姐妹们拜年啦
- python计算思维的概念_用Python学计算思维turtle详解
- 数据库设计的三大范式[学习笔记]
- echart 饼图标题title的详细参数配置
- ROG幻14 AMD R7-4800H VM16安装macOS Catalina 10.15教程
- [导入]polygraph3d三维运行时引擎为silverlight 1.0.zip(15.69 KB)
- 白名单模板_亚马逊白名单申请流程全解析
- 图书管理系统mysql课程设计C_数据库课程设计 图书管理系统 附源代码.doc
- SourceTree和Bitbucket使用时的注意事项
- 航天信息a3服务器怎么打开,航天信息-睿财A3-使用说明.doc
- 【问题】Ucinet密度分析结果一直是1.000
- 某电商用户行为分析-提升GMV
- JS: 刷新iframe的方法
- tzpc-arm trust zone
- android q三星a60,三星GALAXY A60开发者选项怎么打开?
- 腾讯云服务器从购买到使用-第一章-数据库