Essential Features of Android Studio Assistant – Action

This article was originally written by: Gemini, originally published on WeChat public account: mPaaS

https://mp.weixin.qq.com/s/2IC_5SOO25gO3nGgFqh-Lw

Since the last release of the new version of the IDEA plugin, Assistant’s innovative integration method has received unanimous praise. However, the first version of Assistant only introduced basic integration features. The boss hopes that we can add more functionalities, such as displaying the integration status when connecting to Firebase, applying some Gradle plugins, and so on.

Origin – Action

These challenges are definitely not a problem for us. We just need to refer to the integration of Firebase. In fact, most of our business development is based on an “event” model, including both ordinary web back-end and front-end development, and the content related to IDEA is no exception. The user actions that IDEA responds to are generally called Actions. For instance, clicking on an item in the menu corresponds to an AnAction operation. For example, in the previous Assistant-related XML, there was the following code:

<action key="mpaas.integrate_dependencies" label="Click to Add">  ....</action>

We need to handle this Action. Based on the previous Firebase integration method, we first need to register the following content in plugin.xml:

<extensions defaultExtensionNs="com.android.tools.idea.assistant">  <actionHandler implementation="com.alipay.mpaas.assistant.actions.MPIntegrateBaselineActionHandler" />    </extensions>
In this class, override the `getId()` method:
class MPIntegrateBaselineActionHandler: AssistActionHandler {  companion object {    const val ACTION_KEY = "mpaas.integrate_dependencies"  }  override fun getId() = ACTION_KEY}

This corresponds to the content in the above XML. It provides a handleAction method where we can write logic:

  override fun handleAction(actionData: ActionData, project: Project) {    ....  }

So this is where the assistant connects to our code. With the above explanation, we have completed the event response part.

Manipulating Gradle Files

The second step is to manipulate the Gradle files. The IDEA plugin does not have a built-in Gradle engine (which is obviously not cost-effective), but it provides weak support for parsing Gradle DSL through Psi (not full support). It also provides some semantic models to simplify the problem.

We noticed that Android Studio provides a class called GradleBuildModel in Android Studio 3.6, and its interface is as follows:

Essential Features of Android Studio Assistant - Action

Looking at android / buildscript / dependencies / ext, we can immediately see that this corresponds to several DSL blocks in our build.gradle. For example, if we want to add a specific Maven repository to the buildscript to pull SDKs or Gradle plugins, we can operate as follows:

Getting and Modifying GradleBuildModel

GradleModelProvider.get().getBuildModel(project)    //orGradleModelProvider.get().getBuildModel(module)
GradleBuildModel is generally cached by AS after sync is completed, and we can retrieve it with O(1) efficiency. We still take buildscript as an example, which corresponds to BuildScriptModel. The content in build.gradle is as follows:
buildscript {    ext.mpaas_artifact = "mpaas-baseline"    ext.mpaas_baseline = "10.1.68-5"    repositories {        mavenCentral()        jcenter()        google()    }    dependencies {        classpath 'com.android.tools.build:gradle:3.6.3'    }}

So adding an Aliyun Maven repository to `repositories` is very simple. We call the `addMavenRepositoryByUrl` method of RepositoriesModel.

repositoriesModel.addMavenRepositoryByUrl("https://maven.aliyun.com/repository/central")
Writing Back to GradleBuildModel

After this change, the BuildModel temporarily stores the content we just modified, and we still need to write this content back:

WriteCommandAction.runWriteCommandAction(project, buildModel::applyChanges)

The final implementation effect is as follows:

Adding Complex Maven DSL Expressions

Of course, the effect shown in the above video is to add a more complex Maven configuration with name/credential, etc., because RepositoriesModel only provides one way to add a URL. If we want to achieve the above effect, we need to use reflection to operate on the GradleDslBlockModel.
val myDslElementField = GradleDslBlockModel::class.java.getDeclaredField("myDslElement")myDslElementField.isAccessible = trueval myDslElement: GradlePropertiesDslElement = myDslElementField.get(repositoryModel) as GradlePropertiesDslElementval nameElement = GradleNameElement.create("maven")val mavenDslElement = MavenRepositoryDslElement(myDslElement, nameElement)val mavenCredentialsDslElement = MavenCredentialsDslElement(mavenDslElement)mavenCredentialsDslElement.setNewLiteral("username", "xxx")mavenCredentialsDslElement.setNewLiteral("password", "xxx")mavenDslElement.setNewLiteral("url", ALIPAY_MAVEN_URL)mavenDslElement.setNewLiteral("name", "alipay")mavenDslElement.addParsedElement(mavenCredentialsDslElement)myDslElement.setNewElement(mavenDslElement)
After completing the above work, we can manipulate the Gradle files through Actions.

Action State Management

After clicking this button, if there is a prompt to inform the user whether the integration was successful, that would be fantastic:

Essential Features of Android Studio Assistant - Action

This requires a component called ActionStateManager
<extensions defaultExtensionNs="com.android.tools.idea.assistant">  <actionStateManager implementation="com.alipay.mpaas.assistant.actions.MPIntegrateBaselineStateManager" /></extensions>

We also need to write such a component, which inherits from AssistActionStateManager and overrides several classes.

Essential Features of Android Studio Assistant - Action

Here, the getId() returns the ID of the Action you just registered, which is mpaas.integrate_dependencies. Here we can choose from several states that can be returned by getState():

Essential Features of Android Studio Assistant - Action

Of course, you can also create a new state based on the prompts. According to the name of this enumeration and the definition of its parameters, we can understand the meaning represented by each state.
Since this class does not have related callbacks in its lifecycle, if we need an instance of this class, we need to store its instance when AS calls the init method.

Long press the QR code on the right

To see more wonderful shares from developers

Essential Features of Android Studio Assistant - Action

“Developer Talk·DTalk” is collecting Google Essential Features of Android Studio Assistant - Action mobile application (apps & games) related product/technology content from Chinese developers. We welcome everyone to share their insights or discoveries in the mobile application industry, experiences or new findings during mobile development, as well as practical experiences and feedback on related products. We sincerely hope to provide a better platform for these outstanding Chinese developers to showcase themselves and fully leverage their strengths. We will select excellent cases through everyone’s technical content for recommendation by Google Developer Experts (GDE).

Essential Features of Android Studio Assistant - Action Click the screen end | ReadOriginalText | Sign up immediately to participateDeveloper Talk·DTalk”

Essential Features of Android Studio Assistant - Action

Essential Features of Android Studio Assistant - Action

Essential Features of Android Studio Assistant - Action

Leave a Comment

×