preface

This is an introduction to AS plug-in development, which aims to understand the whole development process. The code is rough

The AS plugin is definitely a great tool on our development path. Here are a few of the plug-ins I usually use.

Json Java classes

Quickly generate findViewById code

CodeGlance:

Pre-development preparation

To do a good job, he must sharpen his tools. First we need to prepare the IDE, which uses Intellij, the Community version I downloaded.

Once installed, create a new plug-in development project:

A word about the Project SDK. If you don’t have an SDK, click New and select the one that comes with the software, but it may prompt you that you don’t have a Java JDK. On your own machine, just pick a version of the JDK. I use 1.8.

The newly created project directory is as follows:

We next imitate ECTranslation to write a translation plug-in, because the principle is simple, easy to use, easy to implement. If you see how it works, you can make one yourself.

Because we need to use the API of Youdao Translation, we need to register developers on Youdao Wisdom Cloud first, apply for natural language translation service after registration, and create the application.

The process of requesting the API youdao Translation has a Demo ready for us

I’ll post the Java request process directly:

Public class Demo {public static void main(String[] args) throws Exception {String appKey =" Your appKey"; String query = "good"; String salt = String.valueOf(System.currentTimeMillis()); String from = "EN"; String to = "zh-CHS"; String sign = md5(appKey + query + salt+ "your key "); Map params = new HashMap(); params.put("q", query); params.put("from", from); params.put("to", to); params.put("sign", sign); params.put("salt", salt); params.put("appKey", appKey); System.out.println(requestForHttp("https://openapi.youdao.com/api", params)); } public static String requestForHttp(String url,Map requestParams) throws Exception{ String result = null; CloseableHttpClient httpClient = HttpClients.createDefault(); /**HttpPost*/ HttpPost httpPost = new HttpPost(url); List params = new ArrayList(); Iterator> it = requestParams.entrySet().iterator(); while (it.hasNext()) { Entry en = it.next(); String key = en.getKey(); String value = en.getValue(); if (value ! = null) { params.add(new BasicNameValuePair(key, value)); } } httpPost.setEntity(new UrlEncodedFormEntity(params,"UTF-8")); /**HttpResponse*/ CloseableHttpResponse httpResponse = httpClient.execute(httpPost); try{ HttpEntity httpEntity = httpResponse.getEntity(); result = EntityUtils.toString(httpEntity, "utf-8"); EntityUtils.consume(httpEntity); }finally{ try{ if(httpResponse! =null){ httpResponse.close(); } }catch(IOException e){ e.printStackTrace(); } } return result; } public static string MD5 (string string) {if(string == null){return null; } char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; try{ byte[] btInput = string.getBytes("utf-8"); / * * get the MD5 digest algorithms MessageDigest object * / MessageDigest mdInst = MessageDigest. GetInstance (" MD5 "); /** Update the digest with the specified byte */ mdinst.update (btInput); /** Get ciphertext */ byte[] md = mdinst.digest (); /** Convert the ciphertext to a hexadecimal string */ int j = md.length; char str[] = new char[j * 2]; int k = 0; for (byte byte0 : md) { str[k++] = hexDigits[byte0 >>> 4 & 0xf]; str[k++] = hexDigits[byte0 & 0xf]; } return new String(str); }catch(NoSuchAlgorithmException | UnsupportedEncodingException e){ return null; } /** * public static String getUrlWithQueryString(String) url, Map params) { if (params == null) { return url; } StringBuilder builder = new StringBuilder(url); if (url.contains("?" )) { builder.append("&"); } else { builder.append("?" ); } int i = 0; for (String key : params.keySet()) { String value = params.get(key); If (value == null) {// Filter empty keys continue; } if (i ! = 0) { builder.append('&'); } builder.append(key); builder.append('='); builder.append(encode(value)); i++; } return builder.toString(); Public static String encode(String input) {if (input == null) {return ""; } try { return URLEncoder.encode(input, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return input; }}Copy the code

The principle of

Before development, let’s talk about the principle of translation. The whole translation process is very simple, get the word selected by the mouse, call the translation API, sort out the translation results and display them.

The new version of Youdao Wisdom Cloud’s natural language translation API is no longer free, but users will be given 100 yuan of experience money after registering, and the charging standard is as follows:

If it was for our own personal use, 100 yuan would be enough for us.

Next, enter the formal development process.

Plug-in development Process

Start with a new Action file:

Then enter Action ID, Class Name, and shortcut keys:



In the image above we put the new translate buttonEditUnder the order, the name of the order istranslationThe shortcut key isAlt+E.

Once you’re sure, take a look at plugin.xml and add this code:


  <actions>
    <action id="zttranslation" class="ZTTranslation" text="Translation" description="translate word" icon="/icons/ic_logo.png">
      <add-to-group group-id="EditMenu" anchor="first"/>
      <keyboard-shortcut keymap="$default" first-keystroke="alt E"/>
    </action>
  </actions>Copy the code

This is the configuration file for our new translate Action. To extend this, in the configuration file above, I added an icon to the front of my Action, like this:

We can create an ICONS directory under the Resources directory and add icon images.

Then add the corresponding configuration to the configuration file: icon=”/ ICONS /ic_logo.png”·. When the AS theme changes to black, the Action logo automatically uses the suffix dark.

Let’s take a look at the new ZTTranslation class:

public class ZTTranslation extends AnAction {

    @Override
    public void actionPerformed(AnActionEvent e) {
        // TODO: insert action logic here
    }

}Copy the code

Next we get the word selected by the mouse and pop it up:

public class ZTTranslation extends AnAction { @Override public void actionPerformed(AnActionEvent e) { final Editor mEditor = e.getData(PlatformDataKeys.EDITOR); if (null == mEditor) { return; } SelectionModel model = mEditor.getSelectionModel(); final String selectionTxt = model.getSelectedText(); if (TextUtils.isEmpty(selectionTxt)) { return; } Messages.showMessageDialog(selectionTxt,"TestWord",Messages.getInformationIcon()); }}Copy the code

Let’s run it and see what it looks like.

After running this command, a new window will be opened and a new project will be created.

Our new Translation is in the first line, the following test, select the word:

Everything is fine. Let’s go on to the translation.

@Override public void actionPerformed(AnActionEvent e) { final Editor mEditor = e.getData(PlatformDataKeys.EDITOR); if (null == mEditor) { return; } SelectionModel model = mEditor.getSelectionModel(); final String selectionTxt = model.getSelectedText(); if (TextUtils.isEmpty(selectionTxt)) { return; } / / called youdao translation Demo String result. = HttpUtils findTranslation (selectionTxt); StringBuilder sb = buildResult(result); String translation; If (sb.length() == 0) {translation =" ; } else { translation = sb.toString(); } showTranslationPopup(mEditor, translation); }Copy the code

HttpUtils. FindTranslation (selectionTxt) is the youdao I posted above website request Demo, then returns the string according to the design train of thought to typesetting, translation request to return the result of sample is as follows:

{"errorCode":"0", "query":"good", // There must be "translation": [// if the query is correct, there must be "good"], "Basic" : {/ / youdao dictionary - basic dictionary, word is "phonetic" : "g ʊ d" "UK - phonetic" : "g ʊ d / / English pronunciation" us - phonetic ":" ɡ ʊ d "/ / American pronunciation" explains: "[" benefits", }, "web":[// Youdao Dictionary - Network definition, This result does not necessarily exist {" key ":" good ", "value" : [" good ", "goodness", "good"]}, {...}]], "dict":{ "url":"yddict://m.youdao.com/dict?le=eng&q=good" }, "webdict":{ "url":"http://m.youdao.com/dict?le=eng&q=good" }, "l":"EN2zh-CHS" }Copy the code

‘explains’, and a popup displays:

private void showTranslationPopup(final Editor editor, final String result) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { JBPopupFactory factory = JBPopupFactory.getInstance(); factory.createHtmlTextBalloonBuilder(result, null, new JBColor(new Color(186, 238, 186), new Color (73, 117, 73)), null).setFadeoutTime(5000).createBalloon().show(factory .guessBestPopupLocation(editor), Balloon.Position.below); }}); }Copy the code

Then run it again.

Translation from Chinese into English:

Here is just an example of practice, so did not consider more details, but later look at the source code to deal with uncommon words or very powerful, ha ha.

The last step is to compile and export the plug-in package and run it into our Android Studio.

The plug-in zip package is exported to the project path, and then we quickly open AS to try to install the plug-in.

After the installation is complete, restart the AS.

Release process

Plug-in Information Configuration

Now that we have the plugin ready, if more people find it, we need to publish it to the plugin repository. Let’s take a look at the release process.

First we need to complete the plugin information:

The default configuration file looks like this:

<idea-plugin version="2"> <id>com.your.company.unique.plugin.id</id><! <name>Plugin display name here</name><! -- Plugin name --> <version>1.0</version> <vendor email="[email protected]" url="http://www.yourcompany.com">YourCompany</vendor><! -- The email address and url uploaded to the Plugins repository will be displayed in your plugin interface --> <! -- Your plugin's introduction is also displayed in the Plugins repository information screen --> <description><! [CDATA[ Enter short description for your plugin here.<br> <em>most HTML tags may be used</em> ]]></description> <! <change-notes><! [CDATA[ Add change notes here.<br> <em>most HTML tags may be used</em> ]]> </change-notes> <! -- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -- > < idea - version since - build = "141.0" / > <! -- Product selection, detailed below --> <! -- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html on how to target different products --> <! -- uncomment to enable plugin in all products <depends>com.intellij.modules.lang</depends> --> <! > < Extensions defaultExtensionNs="com.intellij"> <! -- Add your extensions here --> </extensions> <! --Action registration, this code will be automatically generated based on the information we entered at the beginning of the New Action --> <actions> <! -- Add your actions here --> </actions> </idea-plugin>Copy the code

We need to fill in some key information, among which the description must be in English, otherwise it will be called back by the official after it is submitted to the market. Description supports HTML tags, and those unfamiliar can use the online HTML editor directly.

Also note this passage:

<! -- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html on how to target different products --> <! -- uncomment to enable plugin in all products <depends>com.intellij.modules.lang</depends> -->Copy the code

Here are the product types that configure your plug-in to publish to the JetBrains plugin repository.

We all know that JetBrains has many products, such as Android Studio, Intellij, etc., which support plug-ins.

If we comment the code above, our plugin will be uploaded to the Intellij repository by default, which means that our plugin can only be found in Intellij, not in AS… So we uncomment it and upload it to all repositories by default.

With the information configured, we need to recompile the build plug-in.

Sign up for a Jetbrains warehouse account

With the plug-in information ready, we need to register the Repository account: Jetbrains Plugins Repository

After uploading, official review is required, and feedback will be sent to our registered email address. If the format of our configuration file is not correct, for example, I used Chinese description at the beginning, it will be rejected by the market…

If all goes well, an official congratulatory email will arrive a couple of days later and we’ll be able to search for it in the warehouse.