Write an Android Studio Plugin Part 5: Localization and Notifications by Marcos Holgado IntelliJ IDEA is officially recommended to learn IDE plug-in development blog column, hope to have a need for readers to help.

In Part 4 of this series, we learned how to integrate third-party apis such as Jira Cloud Platform into plug-ins and how to develop using patterns such as MVP or MVC. In this article, I’ll partially refactor the plug-in so that we can localize the plug-in and use notifications in a simpler way.

What are we going to do?

Today’s goal is very simple, we will try to clean up the plug-in code. To do this, I’ll focus on two areas: notifications and strings.

We’ll explore a way to remove all the hard coding of strings and create a way to move them to one location, as we all know strings.xml, which will also allow us to internationalize and localize them for free.

Also, instead of the usual boilerplate code, we’ll explore how to move the relevant code into utils when creating a new notification, and we’ll add the option to have a hyperlink in the notification, which we’ll use in the next article.

As always, all of the code for this article can be found in the Part5 branch of the repository below.

Github.com/marcosholga…

Localize the plug-in

Whether you’ve read the previous article or not, there are probably a lot of strings hard-coded in your plug-in, like this:

val lblPassword = JLabel("Token")
Copy the code

Or it

createNotification("Updated"."Welcome to the new version",...).Copy the code

To get rid of these hard-coded strings, we will use Resource Bundles, which are a set of property files with the same base name and language-specific suffixes.

In Android, you can localize your application by adding language-specific suffixes to the Values folder so that values-en/strings.xml can be used in English, values-es/strings.xml can be used in Spanish, You can think of Resource Bundles as equivalent to this.

Your Resource bundles should exist in the Resources folder, and I’ll put them in the deeper messages folder, the full path being Resources /messages/. In it, I’ll start by creating a new properties file called strings_en.properties, where I’ll store strings in English using the following format.

plugin.name = My Jira Plugin
settings.username = Username
settings.token = Token
settings.jiraUrl = Jira URL
settings.regEx = RegEx
...
Copy the code

Now we can create another properties file for another language, and I’m pretty fluent in Spanish, so I’ll create a new strings_es.properties file that looks like this:

plugin.name = Mi Jira Plugin
settings.username = Usuario
settings.token = Token
settings.jiraUrl = Jira URL
settings.regEx = Expresion Regular
...
Copy the code

If we look in the Project window, we can see how our single strings_en.properties file is bundled with our new strings_es.properties in a resource bundle called Strings.

To use the new string, I’ll create a helper class that takes the string resource we created and returns a string based on the property key.

object StringsBundle {
    @NonNls
    private val BUNDLE_NAME = "messages.strings"
    private var ourBundle: Reference<ResourceBundle>? = null

    private fun getBundle(a): ResourceBundle {
        var bundle = SoftReference.dereference(ourBundle)
        if (bundle == null) {
            bundle = ResourceBundle.getBundle(BUNDLE_NAME)
            ourBundle = SoftReference(bundle)
        }
        return bundle!!
    }

    fun message(
        @PropertyKey(
            resourceBundle = "messages.strings"
        ) key: String.vararg params: Any
    ): String {
        return CommonBundle.message(getBundle(), key, *params)
    }
}
Copy the code

If we now wanted to retrieve the name of the plug-in, rather than hard-coding the string where needed, we could simply do the following:

StringsBundle.message("plugin.name")
Copy the code

Now it’s time to replace all hard-coded strings in the plug-in with appropriate localized strings, using either help or our StringsBundle class. 🙂

notice

So far, we’ve created a few notification pop-ups in different places, and we’re repeating the same code over and over again, so I want to simplify the code by having an Utils class to handle the creation of notifications.

In this Utils class, I will create a new method to display notifications. This method will have different parameters, such as the title, the message, and in which item we want to display the notification. Project can be empty because in some cases our notifications will not show up in Project, such as when Project is not loaded.

The other parameter is the type of notification, by default we will display a balloon type notification, which is a display type, not a notification type, we can display INFORMATION, WARNING or ERROR notifications.

The last parameter is the listener class for notifications. You may have noticed that balloon type notifications can have a hyperlink, as shown in the following example.

These hyperlinks are like actions that we can control as needed. Instead of redirecting the user to the corresponding URL in the open browser, we can specify the corresponding behavior using the notification listener class.

The final method is as follows:

fun createNotification(
        title: String,
        message: String,
        project: Project? , type:NotificationType,
        listener: NotificationListener?). {
    val stickyNotification =
            NotificationGroup(
            "myplugin$title",
                    NotificationDisplayType.BALLOON,
                    true
            )
    stickyNotification.createNotification(
        title, message, type, listener
    ).notify(project)
}
Copy the code

Now, you can use this method to replace the old code and use it in your plug-in’s code. The end result should look like this:

Utils.createNotification(
        StringsBundle.message("common.success"),
        StringsBundle.message("issue.moved"),
        project,
        NotificationType.INFORMATION,
        null
)
Copy the code

hyperlinks

Since I’ve already discussed using hyperlinks, I thought I could go a little further.

I’ll add more helper methods to our utils class, which we’ll use in the next article. First, we’ll look at how to integrate hyperlinks in notifications.

To create a hyperlink, we need some HTML code. Our notification message is no longer a simple string, but an HTML string. In the HTML code, we will have to create a new hyperlink using the tag, and since I want to reuse this code, I put the entire HTML string into the resource bundle we created earlier.

utils.hyperlink.code = <html>{0} <a href=\"postResult.get()\" target=\"blank\">{1}</a> {2}</html>
Copy the code

You can see that I have defined three different sections that we can modify as needed, the first for plain text, the second for hyperlinked text, and finally the third for plain text scenarios.

Using the Resource bundle, I can quickly create a new utils method that returns HTML code with the given hyperlink string prefix, hyperlink string, and hyperlink string suffix.

fun createHyperLink(pre:String, link: String, post: String) =
        StringsBundle.message(
            "utils.hyperlink.code", pre, link, post
        )
Copy the code

Finally, I’ll create a new Listener, one of the main things you might want to do when using a plug-in is to allow the user to restart Android Studio to complete the installation of a new version, or because your plug-in has just changed and needs to be restarted.

The new method returns a Listener that detects when a hyperlink event was triggered and restarts the IDE in this case.

fun restartListener(a) =
    NotificationListener { _, event ->
       if (event.eventType === HyperlinkEvent.EventType.ACTIVATED) {
           ApplicationManager.getApplication().restart()
       }
    }
Copy the code

That’s all for this article! You should now be able to localize the plug-in configuration while persisting some data.

Keep in mind that the code in this article is available in the Part5 branch of the GitHub Repo family.

In the next article, we’ll cover templates and how to make them available in plug-ins, ensuring that users can create new projects, modules, or whatever you want with a simple right click. In the meantime, if you have any questions, feel free to comment or follow me on Twitter.


“AndroidStudio plugin” translation series

  • Create a basic plugin for AndroidStudio
  • Write a plugin for AndroidStudio (2): persist data
  • Write a plugin for AndroidStudio (3): setup page
  • Write a plugin for AndroidStudio (4): integrate Jira
  • Writing AndroidStudio plug-ins (5): localization and notifications

About the translator

If you think this article is valuable to you, welcome to ❤️, and also welcome to follow my blog or GitHub.

If you feel that the article is not enough, please also urge me to write a better article by paying attention to it — in case I make progress one day?

  • My Android learning system
  • About the article error correction
  • About paying for knowledge
  • About the Reflections series