Android Studio Plugin Development

We all love plugins. With their help, we can add specific features to existing programs and improve our development experience. But have you ever tried to build your own plugin? In this article we’ll describe a step-by-step process of creating a simple plugin for Android Studio / IntelliJ IDEA. If you are not acquainted with the structure of IDEA plugins, it’s outlined here.
The basic possibilities provided by IntelliJ IDEA are enough for creating plugins of any complexity: from those that resolve applied tasks to those that offer support for custom programming languages. The only difficulty that you may have to deal with is finding relevant documentation. However, you can find answers to almost all possible questions on IDEA’s developer, JetBrains, forum.
Now, let’s see plugin development in action!

What Android Styler plugin is used for

The idea of the Android Styler plugin is to make Android developers’ lives easier when they create an XML layout. Normally, to create a layout.xml file you need to take the following steps:
  1. Make up a required UI layout in layout.xml:
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="match_parent"

android:layout_height="match_parent">



<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:text="@string/stub"

android:textColor="@android:color/black"/>



</LinearLayout>
2. Put repeating or important elements into styles.xml:
<style name="TextStub">

    <item name="android:layout_width">wrap_content</item>

    <item name="android:layout_height">wrap_content</item>

    <item name="android:layout_gravity">center</item>

    <item name="android:textColor">@android:color/black</item>

</style>
Doing this manually isn’t fun: you need to present each XML attribute of view as <item/> tag, just like this:
android:layout_width="wrap_content" -> <item name="android:layout_width">wrap_content</item>
One of the options here is to use a ready-made solution from Android Studio. Let’s see how it works. Press the RMB on each attribute of the View and choose Refactor -> Extract -> Style:
Mark style attributes and set a style name:
Advantages of this approach:
  1. Out-of-the-box solution.
  2. Possible to choose attributes.
  3. Default attributes can be replaced using one line: style="@style/NewStyle."
Disadvantages:
  1. You can’t choose a file for style, which is useful if you hold styles for each type of View in a separate XML (for example, at Yalantis we store our TextView styles in styles_text.xml).
  2. You can’t paste style into a specific place, you can only write it manually in the end of the line.
Even though using the out-of-the-box solution has a lot of advantages, it’s still a good idea to write your own plugin to resolve the layout problem. Moreover, for those who use Android IDEA instead of Android Studio, the "Extract" feature is unavailable.
Here is a user case for working with the plugin:
  1. A developer copied attributes for the future style to a clipboard.
  2. A developer opened the required style.xml.
  3. A developer pressed Ctrl+Shift+D or used a contextual menu to choose "Paste Style".
  4. IDE shows a dialogue window asking to input a name for a new style.
  5. A new style is pasted to the location of caret.
During this operations no errors must appear. Invalid lines must be skipped.
The general process of writing a plugin is as follows:
  1. Prepare a development environment.
  2. Create a project and implement functionalities.
  3. Assemble jar and upload a completed plugin to Plugin Repository.

Preparations

Download Intellij IDEA Community Edition and its sources. The sources are not necessary, but it’s better to use them because they contain Java documentation with classes and methods we are interested in, as well as sources of other plugins whose solutions can be used as hints.  

Development and testing

Create a new project. In the “Project SDK” section choose your IDEA. In case there is no options available in this section, press “New” and choose a path to folder where IDEA is installed.
If you have downloaded the sources, choose File -> Project Structure… and in the "Sourcepath" tab submit the path to the sources.
Now, let’s move to the development process itself.
To put it simple: a plugin for IDEA is a .jar file that contains a config file plugin.xml in  META-INFfolder and code responsible for the plugin’s work.
Start with plugin.xml file. We’ll skip all the obvious things here and get right to the meaty part. For some reason, my IDE couldn’t process the plugin’s dependency on Android Studio:
So I made it accessible for all IDE’s:
<depends>com.intellij.modules.lang</depends>
Next, we need to bind our code with the Ctrl+Shift+D key combination. To do this, we should declare a custom action using the PasteAction class:
<actions>

  <!-- Add your actions here -->

  <action id="3421" class="pro.alex_zaitsev.androidstyler.PasteAction" text="Paste Style"

          description="Paste Style">

      <add-to-group group-id="EditorPopupMenu" anchor="after" relative-to-action="PasteMultiple"/>

      <add-to-group group-id="ConsoleView.PopupMenu" anchor="after" relative-to-action="ConsoleView.Copy"/>

      <add-to-group group-id="EditorActions" anchor="first"/>

      <keyboard-shortcut keymap="$default" first-keystroke="ctrl shift D"/>

  </action>

</actions>

PasteAction class

PasteAction class must extend EditorAction class. Put StylePasteHandler class instance into constructor as EditorActionHandler. In the executeWriteAction (Editor editor, DataContextdataContext) public void method we have access to all elements needed: clipboard, caret, and output document.
First, we get the copied text via a clipboard manager, CopyPasteManager:
private String getCopiedText() {

  try {

      return (String) CopyPasteManager.getInstance().getContents().getTransferData(DataFlavor.stringFlavor);

  } catch (NullPointerException | IOException | UnsupportedFlavorException e) {

      e.printStackTrace();

  }

  return null;

}
Now, let’s ask a user for the style name. Since it’s enough to use a dialog with simple input field, we will use a standard solution:
private String getStyleName() {

  return (String) JOptionPane.showInputDialog(

          new JFrame(), Consts.DIALOG_NAME_CONTENT,

          Consts.DIALOG_NAME_TITLE,

          JOptionPane.PLAIN_MESSAGE,

          null,

          null, "");

}
Next, delete the highlighted text if you have it (default paste behavior):
private void deleteSelectedText(Editor editor, Document document) {

  SelectionModel selectionModel = editor.getSelectionModel();

  document.deleteString(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());

}
Paste the formed XML and move the caret to the end of the pasted text:
CaretModel caretModel = editor.getCaretModel();

// insert new string into the document

document.insertString(caretModel.getOffset(), output);

// move caret to the end of inserted text

caretModel.moveToOffset(caretModel.getOffset() + output.length());
At last, scroll if needed to the end of the pasted piece:
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
Also, I use a bunch of utility classes from the repository:

Launch and debugging

This is incredibly easy. Just push Shift + F10 or the “Run” button:
After that, a new copy of IDEA will launch. Debugging starts by pushing Shift + F9 or the corresponding button on the launch panel.
Here’s where you can find a set of ready-made solutions for plugin development. And check out some more valuable information about plugin development here.

Publishing

To publish our plugin, we first must assemble it as JAR. To do that, choose Build -> Prepare Plugin For Deployment:
If assembling and archivation are successful, IDEA will show the following notification:
That’s it! The plugin is ready for deployment. Now we can upload it to JetBrains Plugin Repository. The process is intuitive, so we won’t go deep here. After the first publication, as well as after each update, the plugin passes an approvement stage that may take up to three days.
Here’s how AndroidStyler plugin page in the JetBrains repository looks like.
If you processed the "depends" block in the plugin.xml file correctly, the plugin will be available for installation in the IDE that you have allowed:
Now you know how to eliminate inconveniences in your JetBrains IDEA in case there are no out-of-the-box solutions within your reach.
Don’t forget to check out my AndroidStyler plugin source code on GitHub.

Comments

All Post

MINI MILITIA RANK HACK APK FOR ANDROID ROOT & CYDIA iOS

Android SQLite Example Application Using Kotlin

Shortcut Virus?

DV Infosys

Paying with Your Face

Microsoft’s giving you just 10 days now, not 31, to change your mind about Windows 10

Does your iPhone suffer from 'Touch Disease'?

Google’s Quantum Dream May Be Just Around the Corner