IntelliJ IDEA/Android Studio插件开发入门指南

IntelliJ IDEA/Android Studio插件开发入门指南


基于IntelliJ平台的产品都可以通过添加插件来丰富其原有的功能,JetBrains团队也我们提供了丰富的API来进行插件开发,所有的插件都可以在JetBrains Plugin Repository找到。常见的插件类型有:

  • 自定义语言支持(如Java、Kotlin)
  • 框架集成
  • 工具集成
  • 用户界面插件

这些类型插件的介绍以及功能就不一一细说了,官网也有比较详细的介绍。
简单来说,IDEA也好Android Studio也好(以下统一称为IDE),它们为插件提供了运行环境,通过各种插件的配合来实现不同的功能。下面就先介绍开发IDEA插件前需要哪些准备。

  • 安装IDEA,如果想在开发插件的过程中进行Debug,那么还需要把IDEA的源码下载下来(Github源码地址)
  • 配置IntelliJ Platform SDK,也就是开发插件所需的SDK,类似开发Android应用时需要Android SDK,并且插件都是运行在JVM上的,所以也需要配置JDK的路径
  • 指定Sandbox Home目录,Sandbox Home目录用于存放插件项目实例的一些配置文件。在macOS系统中默认存放路径是/Users/{用户名}/Library/Caches/IdeaIC2018.2/plugins-sandbox

配置SDK,如果你把IDEA源码也下载了,那么还需要配置一下源码的路径


添加SDK.jpg
选择源码路径.jpg

环境搭建好了,那么接下来我们就创建一个简易的插件工程,依次点击File->New->Project然后在弹出框左栏选择Gradle,然后在右侧一栏勾选IntelliJ Platform Plugin(如果想要使用Kotlin进行开发就把Kotlin那一项也勾选上)

新建插件项目.jpg

项目创建好后长这样:


项目结构.jpg

创建Action

插件可以自定义IDE的UI,在菜单或工具栏中新加入一个Item。SDK提供了一个类AnAction,这个类的actionPerformed方法在你每次在菜单栏中选中或在工具栏中点击对应项时都会被调用。创建一个Action只需要两步:

  • 定义派生于AnAction的类
  • 注册Action

当然你也可以定义一组派生于AnAction的类

定义Action

下面的代码是我仿照官方例子定义的一个Action,只是把Java改成了Kotlin实现

class TextBoxes : AnAction("Text _Boxes") {

    override fun actionPerformed(e: AnActionEvent) {
        val project = e.getData(PlatformDataKeys.PROJECT)//这个Project是不是很熟悉?它其实跟Gradle中的Project意义是一样的
        val txt = Messages.showInputDialog(project, "What is your name?", "Input your name", Messages.getQuestionIcon())
        Messages.showMessageDialog(project, "Hello, $txt!\\n I am glad to see you.", "Information", Messages.getInformationIcon())//这两段代码其实很简单,都不用解释了
    }
}
注册Action

定义好Action之后当然就需要告知IDE你有哪些Action啦,所以就需要对这些Action进行注册,注册的方式有两种(是不是似曾相识的感觉?)。

  • plugin.xml文件的<actions>标签中进行注册
  • 在代码中进行注册
在plugin.xml文件中进行注册

跟Android开发中在AndroidManifest.xml文件中注册组件非常相像,我们只需要按照IntelliJ平台的规范在plugin.xml文件的<actions>部分内容进行修改:

<actions>
  <group id="MyPlugin.SampleMenu" text="_Sample Menu" description="Sample menu">
    <add-to-group group-id="MainMenu" anchor="last"  />
       <!--把这组Action加到"MainMenu"中-->
       <action id="Myplugin.Textboxes" class="Mypackage.TextBoxes" text="Text _Boxes" description="A test menu item" />
  </group>
</actions>

下面对plugin.xml的规范做一些介绍:

<!-- Actions -->
    <actions>
    <!-- <action>对Action进行注册,
         "id"定义了这个Action的唯一识别id,
         "class"用于指定该Action对应类的全路径,
         "text"定义这个Action在菜单栏或者工具栏中显示的文本,前面加_表示在该字符下加下划线,
         "use-shortcut-of" 可选项 指定使用和某一个Action一样的快捷键
         "description" 可选项 对Action的描述(当你的鼠标指针停留在该item时就会显示该内容)
         "icon"没啥好说的-->
    <action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Collect _Garbage" description="Run garbage collector" icon="icons/garbage.png">
        <!-- <add-to-group>节点表示指定Action被加入到已存在的一个组中,
             "group-id"表示加入的组的id,
             "anchor"指定Action相对于组中其他Action的位置,可以指定的值有"first", "last", "before", "after"
             "relative-to-action"如果把"anchor"的值设置为"before"或者"after"时,必须为该属性赋值,表示相对于某一个Action的位置-->
        <add-to-group group-id="ToolsMenu" relative-to-action="GenerateJavadoc" anchor="after"/>
        <!-- <keyboard-shortcut>指定Action的快捷键
             "second-keystroke"指定Action次选快捷键
             "keymap"指定Action的快捷键映射到哪一个系统中,可以设定的值作为常量定义在
             com.intellij.openapi.keymap.KeymapManager类中-->
        <keyboard-shortcut first-keystroke="control alt G" second-keystroke="C" keymap="$default"/>
        <!-- 指定鼠标快捷键 -->
        <mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
    </action>

使用代码进行注册

使用代码注册其实也没什么少介绍的,贴一段官方代码大家就大致了解了,就是调用相应的api去做一些配置

public class MyPluginRegistration implements ApplicationComponent {
  // Returns the component name (any unique string value).
  @NotNull public String getComponentName() {
    return "MyPlugin";
  }


  // If you register the MyPluginRegistration class in the <application-components> section of
  // the plugin.xml file, this method is called on IDEA start-up.
  public void initComponent() {
    ActionManager am = ActionManager.getInstance();
    TextBoxes action = new TextBoxes();

    // Passes an instance of your custom TextBoxes class to the registerAction method of the ActionManager class.
    am.registerAction("MyPluginAction", action);

    // Gets an instance of the WindowMenu action group.
    DefaultActionGroup windowM = (DefaultActionGroup) am.getAction("WindowMenu");

    // Adds a separator and a new menu command to the WindowMenu group on the main menu.
    windowM.addSeparator();
    windowM.add(action);
  }

  // Disposes system resources.
  public void disposeComponent() {
  }
}

上面两种注册方式是不是都感觉挺麻烦,在AS中我们创建一个Activity的时候可以通过File->New->Activity来帮我们创建一个Activity,并且已经帮我们注册到AndroidManifest.xml中,甚至是布局文件也创建好了,那么IDEA能做到吗?答案是肯定的,而且步骤也大同小异:

快速创建Action.jpg

接下来我们点击运行或Debug即可看到运行效果

运行效果1.jpg

运行效果2.jpg
运行效果3.jpg

到这里相信你也了解了怎么样去创建并运行一个简单的IDEA插件了,整个过程是不是和开发一个Android应用非常相像呢,其实都可以把他们看成是开发一个带UI界面的JVM应用程序,当你开发好一个插件之后,需要将其上传到远程仓库中以供他人使用,整个流程和发布一个第三方库也是大同小异。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335