基于IntelliJ IDEA/Android Studio插件开发指南(推荐)

目录
  • 前言
  • 插件开发的基本流程
    • 1. 环境配置
      • 1.1 安装PDK
      • 1.2 配置插件开发SDK
    • 2. 新建插件工程
    • 3. Action
    • 4. 配置描述
    • 5. 调试、打包
  • 业务实践
    • 方案一:自建Diff工具
    • 方案二:使用JGit
    • 方案三:利用内存Git

为防止盗链,本文首发于于果的博客园,转载请注明出处!原文链接:https://www.cnblogs.com/yuxiuyan/p/14682460.html

前言

目前在为安卓手机QQ做自动化的相关工作,包括UI自动化,逻辑层自动化等。使用到的uiautomator等框架,需要在Android Studio进行编码工作。
其中很多工作如果做到插件化的话,可以有效地节省时间成本,提升大家的自动化效率。
比如运行自动化的时候,需要用到我们自定义的shell命令。我们可以通过插件来实现一键运行。
在运行adb shell am instrument命令的时候,需要编译出test APKtarget APK。手Q整体的git仓库很大,编译耗时很久。我们想着通过一些方法来优化这个耗时。其中一个步骤就是,把我们代码目录下的变更,同步到一个编译目录下。
这个小功能的最合适的形态,自然就是Android Studio上的一个插件。点击一个按钮,一键同步,那可真是在米奇妙妙屋吃妙脆角——妙到家了!
Android Studio是基于Intellij IDEA开发的,所以开发Android Studio的插件,其实就是开发IDEA的插件。
根据官方推荐,使用IDEA IDE来开发IDEA插件。

插件开发的基本流程

1. 环境配置

1.1 安装PDK

正如Java开发需要安装Java DevKit,IDEA插件开发也需要安装Plugin DevKit。PDK的作用是为插件提供IDEA内建支持以及相关库函数。
打开Intellij IDEA --> Preferences --> Plugins,如果没有安装,可以在marketplace里面搜索,并安装。

1.2 配置插件开发SDK

配置开发 IntelliJ 平台插件的SDK也就是IntelliJ Platform Plugin SDK,基于 JDK 之上运行,类似于开发 Android 应用需要 Android SDK。
切换到 File --> Project Structure,选择左侧栏 Platform Settings 下的 SDKs,点击+按钮,先选择 Add JDK,指定 JDK 的路径;再选择Add IntelliJ Platform Plugin SDK,指定上面添加的JDK为插件需要的JDK。需要注意的是,从IDEA 2020.3开始,不能再使用Java1.8版本。因为IDEA 2020.3版本基于Java11构建,所以如果想要开发2020.3及以后版本的IDEA的插件,需要选择Java11版本。

2. 新建插件工程

File --> New --> Project,在弹出的窗口中选择Gradle,然后选择Java(这表明我们使用Java语言开发)和Intellij Platform Plugin,点击Next,然后设置项目的名称和位置,点击Finish完成创建。

3. Action

我们在IntelliJ自定义的插件可以添加到菜单项目(如右键菜单中)或者是放在工具栏中。当用户点击时触发一个动作事件,IntelliJ则会回调AnAction子类的actionPerformed函数。因此我们只需重写actionPerformed函数即可。我们可以认为Action是插件的触发入口。我们可以直接右键New --> Plugin DevKit --> Action新建action,这个action是AnAction的子类。

在接下来的弹出窗口中,我们可以创建一个Action。

  • Action ID:这个action的唯一标识
  • Class Name:action的类名
  • Name:action的名称
  • Description: action的描述信息
  • Groups:这个标签指定我们自定义的插件应该放入到哪个菜单下面。 在IntelliJ IDEA菜单栏中有很多菜单如File、Edit、View、Navigate、Code、……、Help等。他们的ID一般是菜单名+Menu的方式。比如,我们想将我们自定义的插件放到Help菜单中,作为Help菜单的子选项。那么在Groups中就指定HelpMenu。左侧的Anchor属性用于描述位置,主要有四个选项:first、last、before、after。他们的含义如下:

first:放在最前面
last:放在最后
before:放在relative-to-action属性指定的ID的前面
after:放在relative-to-action属性指定的ID的后面

Keyboard Shortcuts:可以为这个action指定快捷键

public class TestAction extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        NotificationGroup notificationGroup = new NotificationGroup("testid", NotificationDisplayType.BALLOON, false);
        /**
         * desc: 这是一个IDEA的通知,会通知到idea右下角的悬浮小窗
         * content :  通知内容
         * type  :通知的类型,warning,info,error
         */
        Notification notification = notificationGroup.createNotification("测试通知", MessageType.INFO);
        Notifications.Bus.notify(notification);
    }
}

创建完之后,我们也可以在src/resources/META-INF/plugin.xml中,看到我们之前写入的action信息,如果想要修改,可以在这个配置文件中直接修改。

  <actions>
        <!-- Add your actions here -->
        <action id="testId" class="com.example.yuguo.TestAction" text="通知" description="测试通知的功能">
            <add-to-group group-id="ToolsMenu" anchor="first"/>
        </action>
    </actions>

4. 配置描述

src/resources/META-INF/plugin.xml是整个插件的配置文件,里面定义了插件的名称,描述信息,支持的IDEA版本号,作者信息,action的相关信息等。

<idea-plugin>
    <!--插件的id,属于全局唯一标识-->
    <id>plugin.test</id>
    <!--插件的名称-->
    <name>PluginTest</name>
    <vendor email="xxxx@example.com" url="">author_name</vendor>

    <!--插件的描述信息,支持html-->
    <description><![CDATA[
    Plugin Test<br>
    <em>v1.0</em>
    ]]></description>

    <extensions defaultExtensionNs="com.intellij">
        <!-- Add your extensions here -->
    </extensions>

    <actions>
        <!-- 这里是刚刚定义的插件信息 -->
        <action id="testId" class="com.example.yuguo.TestAction" text="通知" description="测试通知的功能">
            <add-to-group group-id="ToolsMenu" anchor="first"/>
        </action>
    </actions>
</idea-plugin>

5. 调试、打包

调试

等到配置完成后,在IDEA右侧的Gradle一栏中,有Intellij的集合。点击里面的runIde,可以打开一个沙盒,里面运行包含着该插件的IDEA实例。也可以右键选择debug模式运行。

打包

点击上图的buildPlugin,就可以在build/distributions/目录下面生成插件zip包,这个包就是我们需要的最终产物。在IDEA设置Preferences --> Plugins,点击installed旁边的设置按钮,选择Install Plugin from Disk,然后选择这个zip,就可以安装到IDEA中了。

插件的组件

GUI

ToolWindow

工具视窗(ToolWindow)的功能主要是进行信息的显示,同时用户还可以直接在toolwindow中进行操作调用工具,比如IDE下方默认的terminal、Git等。作为IDE侧边栏中较大的一部分,toolwindow与用户的交互在整个ui中非常重要。

实现toolwindow主要分为两步,第一步创建类实现ToolWindowFactory接口,编写需求的toolWindowFactory实例,第二步在plugin.xml中注册该ToolWindow。

当用户单击工具窗口按钮时,将调用工厂类的方法createToolWindowContent(),并初始化工具窗口的UI。此过程可确保未使用的工具窗口不会在启动时间或内存使用上造成任何开销:如果用户不与插件的工具窗口进行交互,则不会加载或执行任何插件代码。

public class ToolFactoryCompute implements ToolWindowFactory {

    private ToolWindow myToolWindow;
    private JPanel myPanel;
    private JTextArea textContent;
    private JScrollPane myScrollPane;

    /**
     * @param project 项目
     * @param toolWindow 窗口
     */
    @Override
    public void createToolWindowContent(@NotNull Project project,
                                        @NotNull ToolWindow toolWindow) {
        myToolWindow = toolWindow;

        // 将显示面板添加到显示区
        ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
        Content content = contentFactory.createContent(mPanel, "Control", false);
        toolWindow.getContentManager().addContent(content);
    }

}

在plugin.xml中注册toolwindow。

<extensions defaultExtensionNs="com.intellij">
  <!-- canCloseContents表示是否可以关闭这个toolwindow, anchor表示toolwindow的位置, id是toolwindow的名字, factoryClass表示toolwindow的工厂类 -->
  <toolWindow canCloseContents="false" anchor="bottom"
              id="Compute Code Lines" icon="/myToolWindow/test.png"
              factoryClass="tools.ToolFactoryCompute">
  </toolWindow>

</extensions>

Dialog

会话框(Dialog)可以与用户交互,获取用户自定义输入的内容,也可以作为提示弹窗,告诉用户信息。会话框的实现需要定义一个继承了IDEA的DialogWrapper抽象类的子类,这个子类就是自定义的会话框实现,所有的样式定义、功能触发都是放到这个子类里的,比如以下实现:

public class FormTestDialog extends DialogWrapper {

    private String projectName; //假如需要获取到项目名,作为该类的属性放进来

    // DialogWrapper没有默认的无参构造方法,所以需要重写构造方法,它提供了很多重载构造方法,
    // 这里使用传project类型参数的构造方法,通过Project对象可以获取当前IDEA内打开的项目的一些属性,
    // 比如项目名,项目路径等
    public FormTestDialog(@Nullable Project project) {
        super(project);
        setTitle("表单测试"); // 设置会话框标题
        this.projectName = project.getName();
    }

    // 重写下面的方法,返回一个自定义的swing样式,该样式会展示在会话框的最上方的位置
    @Override
    protected JComponent createNorthPanel() {
        return null;
    }

    // 重写下面的方法,返回一个自定义的swing样式,该样式会展示在会话框的最下方的位置
    @Override
    protected JComponent createSouthPanel() {
        return null;
    }

    // 重写下面的方法,返回一个自定义的swing样式,该样式会展示在会话框的中央位置
    @Override
    protected JComponent createCenterPanel() {
        return null;
    }
}

业务实践

获取文件差异

方案一:自建Diff工具

为了获得代码目录与编译目录的文件差异,必然要使用到Diff工具,这其中涉及到很多自定义的规则,比如差异文件是否要忽略等。优点是可以完全自定义灵活的识别差异的规则。缺点是耗时较久,毕竟要编写一套Diff系统。时间比较紧,所以这个方案pass了。

方案二:使用JGit

JGit是Java编写的一套Git工具,通过Java代码就可以调用到Git的所有指令,可以完美解决获得文件差异的需求。但是经过实际测试发现,在调用git.status.call()方法时 ,由于它需要初始化Git,包括建立diff,filetree等操作,对于大仓库,一次运行就要十几秒,不能接受,故放弃。

Git git = Git.open(new File("~/source-code.temp-1/git"));
    Status status = git.status().call();        //返回的值都是相对工作区的路径,而不是绝对路径
    status.getAdded().forEach(it -> System.out.println("Add File :" + it));      //git add命令后会看到变化
    status.getRemoved().forEach(it -> System.out.println("Remove File :" + it));  ///git rm命令会看到变化,从暂存区删除的文件列表
    status.getModified().forEach(it -> System.out.println("Modified File :" + it));  //修改的文件列表
    status.getUntracked().forEach(it -> System.out.println("Untracked File :" + it)); //工作区新增的文件列表
    status.getConflicting().forEach(it -> System.out.println("Conflicting File :" + it)); //冲突的文件列表
    status.getMissing().forEach(it -> System.out.println("Missing File :" + it));    //工作区删除的文件列表

方案三:利用内存Git

经过方案二,我们发现git是符合我们要求的,但是因为JGit要初始化,所以耗时较久。但是我们在运行IDEA的时候,在终端使用git status非常快,是毫秒级,那我们完全可以利用内存中的git,直接执行git status命令,在返回结果中去匹配文件差异。
通过让Java执行git命令,可以达到毫秒级相应。

Java执行shell命令并返回执行结果

 /**
     * 执行shellCommand命令,获取命令的返回结果。在返回结果中,把符合条件的文件名放置到文件集合中
     *
     * @param cmd shell命令
     * @return 命令的输出结果
     */
    public static String executeCommand(String[] cmd) throws IOException {
        String resultStr = "";
        // 利用runtime去执行shell命令
        Process ps = Runtime.getRuntime().exec(cmd);
        // 获取process对象的正常流和异常流
        try (BufferedReader brInfo = new BufferedReader(new InputStreamReader(ps.getInputStream()));
             BufferedReader brError = new BufferedReader(new InputStreamReader(ps.getErrorStream()))) {
            StringBuilder stringBuffer = new StringBuilder();
            String line;
            // 读取输出结果,按照每行读取
            if (brInfo.readLine() != null) {
                while ((line = brInfo.readLine()) != null) {
                    stringBuffer.append(line).append("\n");
                    // 处理文件差异
                    filterFiles(line);
                }
            } else {
                // 如果正常输出流为null,那么就获取异常流
                while ((line = brError.readLine()) != null) {
                    stringBuffer.append(line).append("\n");
                }
            }
            // 等待shell命令执行完成
            ps.waitFor();
            resultStr = stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // shell命令的返回结果
        return resultStr;
    }

    // 在main函数中测试
     public static void main(String[] args) {
        String cmd = "git status";
        String resultStr = executeCommand(new String[]{"/bin/sh", "-c", cmd});
        System.out.println(resultStr);
    }
    

参考

https://blog.csdn.net/huachao1001/article/details/53856916

https://blog.csdn.net/huachao1001/article/details/53883500

https://plugins.jetbrains.com/docs/intellij/welcome.html?from=jetbrains.org

到此这篇关于基于IntelliJ IDEA/Android Studio插件开发指南(推荐)的文章就介绍到这了,更多相关IDEA Android Studio插件开发内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Intellij Idea插件开发之创建项目层级的右键菜单

    在使用Android Studio的过程中,发现自带的一些插件无法满足项目的实际需要,便着手自己开发对应的插件.下面是我开发插件过程中的一个记录,会持续和大家分享. 分享一:创建Project右键菜单 1,按照项目向导一步一步创建一个Demo项目,就不再介绍了,可以参照这篇文章http://www.jb51.net/article/135535.htm 2,创建Action,在plugin配置文件中你会看到 <action id="FirstAction" class="

  • 详解如何使用Android Studio开发Gradle插件

    缘由 首先说明一下为什么会有这篇文章.前段时间,插件化以及热修复的技术很热,Nuwa热修复的工具NuwaGradle,携程动态加载技术DynamicAPK,还有希望做最轻巧的插件化框架的Small.这三个App有一个共同的地方就是大量的使用了Gradle这个强大的构建工具,除了携程的框架外,另外两个都发布了独立的Gradle插件提供自动化构建插件,或者生成热修复的补丁.所以学习一下Gradle插件的编写还是一件十分有意义的事. 插件类型 Gradle的插件一般有这么几种: 一种是直接在项目中的g

  • Intellij IDEA插件开发入门详解

    现今的IDE尽管有如"洪水猛兽"般强大,但要知道再强大的IDE也没法提供给使用者想要的一切功能,所以IDE一般都提供有API接口供开发者自行扩展.下面以Intellij IDEA 12下的插件开发为例,来看一下如何进一步增强IDE以适应开发者的需求. 1.创建Plugin工程 如果Module SDK中没有可选的SDK,那么点击New新添加一个SDK,目录就选择Intellij的安装位置即可. 创建出的Plugin项目结构很简单,只是在META-INF下多了一个plugin.xml配置

  • idea插件开发之弹出框的示例代码

    前言 IntelliJ平台的用户界面广泛使用弹出窗口,即没有chrome(显式关闭按钮)的半模式窗口,在焦点丢失时自动消失.在插件中使用这些控件可以确保插件和IDE其他部分之间的用户体验一致. 弹出窗口可以选择性地显示标题,也可以移动和调整大小(并支持记住它们的大小),并且可以嵌套(当选择一个项目时显示另一个弹出窗口). 一.JBPopupFactory JBPopupFactory 是idea 提供给用户自定义窗口的接口,比较常见的方法如下 createComponentPopupBuilde

  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    之前因为项目组有自己的代码规范,为了约束平时的开发规范,于是基于2019.1.3版本开发了一个代码提示的插件.但是在把IDEA切换到2020.1版本的时候,却发现疯狂报错,但是网上关于IDEA插件开发的相关文章还是不够多,只能自己解决.于是根据官方的SDK文档,使用Gradle重新构建了一下项目,把代码拉了过来.下文会根据2020.1版本简单开发一个代码异常的提示插件,把容易踩坑的地方提示一下. 1.首先先根据IDEA插件开发官方文档,用Gradle新建一个project 选中file -> n

  • 基于IntelliJ IDEA/Android Studio插件开发指南(推荐)

    目录 前言 插件开发的基本流程 1. 环境配置 1.1 安装PDK 1.2 配置插件开发SDK 2. 新建插件工程 3. Action 4. 配置描述 5. 调试.打包 业务实践 方案一:自建Diff工具 方案二:使用JGit 方案三:利用内存Git 为防止盗链,本文首发于于果的博客园,转载请注明出处!原文链接:https://www.cnblogs.com/yuxiuyan/p/14682460.html 前言 目前在为安卓手机QQ做自动化的相关工作,包括UI自动化,逻辑层自动化等.使用到的u

  • 第一次使用Android Studio时你应该知道的一切配置(推荐)

    [开发环境] 物理机版本:Win7旗舰版(64位) Android Studio版本:2.1正式版 [Android Studio的优势] •基于Gradle的构建支持 •Android特定重构和快速修复 •更加丰富的模板代码,让创建程序更简单 •提示工具更好地对程序性能.可用性.版本兼容和其他问题进行控制捕捉 •直接支持ProGuard和应用签名功能: •自带布局编辑器,可以让你拖放UI组件,并在多个屏幕配置上预览布局等: •内置Google云支持: •内置svn.git工具支持: •支持插件

  • 浅析Android Studio 3.0 升级各种坑(推荐)

    点击 Check for Updates 增量更新: 下载完成,会提示更新 您将 Gradle 更新至 4.1: 这里建议您对老项目先暂时点击 Don't remind me on this project,以防有坑.当然我不入地狱谁入地狱,我点 Update,于是问题来了,一直处于下载中,不过,莫担心,我下载好了,公众号聊天界面回复「 gradle-4.1-all 」,下载 gradle-4.1-all.zip 文件,放到: 重启 Android Studio. gradle 目录: Mac系

  • Android Studio 代理配置指南(小结)

    Android Studio 用户的代理配置指南,真正有效的 gradle 代理配置方式.#依赖拉不下来真让人自闭,不想再一遍又一遍自闭了,所以记下来. IDE HTTP Proxy Windows 下 Ctrl + Alt + S ,然后输入 Proxy 能看到 HTTP Proxy  的设置项了,具体的路径是 Appearance & Behavior > System Settings > HTTP Proxy ,macOS 那边对应 Settings 的是 Preference

  • Android Studio 3.6 新特性一览(推荐)

    设计 设计编辑器 设计编辑器(比如布局编辑器和导航编辑器)现在提供了一个拆分视图模式,能够同时查看 UI 界面的 Design 视图和 Code 视图.拆分视图取代并改进了早期的预览窗口,并且可以对每个文件进行设置,并且可以保存上下文信息,比如:缩放比例和设计视图选项等.想要开启拆分视图,单击编辑器窗口右上角的拆分图标即可.相关文档:https://medium.com/androiddevelopers/android-studio-design-tools-ux-changes-split-

  • 基于android studio的layout的xml文件的创建方式

    1.第一步在android studio的project视图模式下右击res文件夹 2.然后找到New --> Android resources file选项,点击进入,按照以下的提示写完: 3.选完后点击OK即可(点击添加layout direction后Directory name将会改变改回自己想要的即可): 4.完成. 结论: 刚开始用android studio的时候,在android工程视图下,不管在res怎么建立新的文件夹,都是看不见的. 从网上找到的方法不知怎么的老是有错,终于

  • Android studio 切换flutterSDK之后报错及解决办法(推荐)

    Windows系统上面修改了flutter sdk的环境变量地址之后Android studio上面运行flutter项目就会报错 类似于: Could not read script XXX\flutter.gradle' as it does not exist. 还有这样:flutter:Warning! The 'flutter' tool you are currently running is from a different Flutter repository 解决办法: 1.首

  • 记录Android studio JNI开发的三种方式(推荐)

    概述 在Andorid Studio不支持JNI开发之前大家一般都是使用Eclipse开发JNI,各种配置让人觉得很蛋疼.从Andorid Studio支持JNI开发后,让我们开发JNI变的如此简单. NDK 和 JNI介绍 JNI (Java Native Interface)是一套编程接口,用来实现Java代码和其他语言(c.C++或汇编)进行交互.这里需要注意的是JNI是JAVA语言自己的特性,也就是说JNI和Android没有关系.在Windows下面用JAVA做开发也经常会用到JNI,

  • Android Studio 常见问题及解决方法(推荐)

    一.Error:All flavors must now belong to a named flavor dimension 问题描述: Error:All flavors must now belong to a named flavor dimension. 解决办法: 应该是因为使用了productFlavors分包,解决方法就是在build.gradle中的defaultConfig中添加一个flavorDimensions "1"就可以了,后面的1一般是跟你的version

  • Android Studio 中Gradle配置sonarqube插件(推荐)

    目录 一,使用公共Maven仓库: 二,使用私有Maven仓库: Sonarqube作为一个很实用的静态代码分析工具,在很多项目中都使用.Android自然也不例外.这里就分享下使用Android Studio时如何在Gradle里配置Sonarqube. 以下分别就使用公共maven仓库和私有maven仓库两种情况来简单说明下: 一,使用公共Maven仓库: 这个比较简单. 打开gradle sonarqube插件官方网址:https://plugins.gradle.org/plugin/o

随机推荐