📜 ⬆️ ⬇️

ADB Uninstall plugin for Android Studio (IntelliJ IDEA)


It so happened that I lost one argument and I had to shave baldly. Since nothing else held back the flow of fresh ideas to my head, and it seemed a shame to appear on the street, then I set out to write a socially useful plugin for one of the best development environments. The functionality is simple, like a maize cob, but very necessary (I’m not sure why I’m not sure why it's not built in by default). So, today I will try to share the experience of developing a plug-in that will allow you to elegantly remove applications that you are working on connected Android devices.

For those who just want to start using, here’s what it looks like (called by AltGraph + U ):

Download from here (ver. 1.0.1): github.com/Ghedeon/ADB-Uninstall/releases
Installation: Settings → Plugins → Install plugin from disk ...
Important: The plugin is raw, so I really hope that those who have installed will unsubscribe about the problems. I will correct as far as possible. Reviews, comments, suggestions for expanding the functionality - everything is welcome!

Here are some everyday scripts of Android developers (especially when working in a team):

Use-Case 1:
The team works on one application. You have just exchanged devices with someone and patiently wait for the installation to complete. What is the result? That's right, Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]. It is logical, because on the device there is an application from a colleague, debug keys , with which applications are signed are different, respectively, the update does not work. Cursing, you climb into the command line, type "adb uninstall <package>" and almost physically feel how the program is being demolished bytes.
')
Use-Case 2:
All the same, only after "adb uninstall" nothing happens, because your system does not have one, but two devices and adb does not know from which to delete. Having embraced the whole stupidity of the situation with your brain, in frustrated feelings you type "adb devices" , get a list of devices, then "adb -s <deviceId> uninstall <package>" and the world surrenders to you.

Use-Case 3:
You have several connected devices and you need to remove from all. Well, here the laziest will go to write a script that at least somehow automates the whole kitchen.

Use-Case 4:
There are no problems, but you are just too lazy to write "adb uninstall <package>" .

Solutions:

Actually, I was interrupted by the script until recently, and it completely suited me, until the authorities demanded to make more active contacts in the team. The option to be interested in the health of someone's parrot, trying to withstand the sincerely concerned anxiety, was rejected as hopeless, so I decided to make a more cross-platform solution of my craft and go with it to people.
Script itself
 #!/bin/bash package=`grep -o 'package=".*"' AndroidManifest.xml | grep -o \".* | sed 's/"//g'` #adb uninstall $package adb devices | tail -n +2 | awk '{print $1}' | xargs -I {} adb -s {} uninstall $package 


Development


About plug-ins for IDEA on Habré has already been written, which is only worth a monumental translation in seven parts from Lucyfer , so I’ll omit the general structure and configuration of IDE. In order to add your own item in the menu and / or toolbar, we inherit from AnAction and override the actionPerformed () method. First of all, we learn the absolute path to the Android SDK :
 ProjectRootManager.getInstance(event.getProject()).getProjectSdk().getHomePath(); 

if we add /platfrom-tools to this, then we will have the path to the working folder, from where we can run adb .
Note
Initially, I decided to go a different way: to hope that the user has all the paths to the Android SDK correctly configured in the environment variables and just pass them on to my process. Then we do not need an absolute path, the interpreter will know about the commands that we want to run. However, under Linux and Mac OS , environment variables, as you know, can be stuffed into a thousand and one relatively decent places, which prevented me from saying with certainty what I would have in System.getenv() . In general, with certain settings of the system, this method collapsed and I decided to retreat. Later, after digging into the source code of the android plug-in for IDEA, I discovered that they, like me, use absolute paths.

Get the list of connected devices:
 Process pr = Runtime.getRuntime().exec(toolPath + File.separator + "adb devices"); 

I used Runtime.exec Runtime.exec() from Java, but at the same time IDEA offers a kosher GeneralCommandLine for such cases. In truth, this transition is still in my TODO and I will be very grateful if someone shares their experience.

Now you need to determine the name of the package that will be deleted. There may be options. An Android project may contain several executable modules with different package names. There may still be Library Projects , but we are not talking about them. The first thing that came to mind was to take the package name from the AndroidManifest.xml of the currently active module. But it turned out to be not very convenient, you can work in the wrong module that you want to remove, so you had to first select the desired module with the mouse. As a result, I stopped at a much more logical solution - to extract the package name from the manifest of the module specified in the current launch configuration. I will explain. As you know, to install an application, you need at least one Run Configuration . When you create this very Run Configuration , in the General tab, you specify the Module . From the manifest of the specified module we will take the package name. If there are several configurations, we will take the one that is currently active.
We get the active configuration:
 RunManager runManager = RunManager.getInstance(event.getProject()); ModuleBasedConfiguration selectedConfiguration = (ModuleBasedConfiguration) runManager.getSelectedConfiguration().getConfiguration(); 

The next step is to find the exact path to the folder with AndroidManifest.xml . In the case of projects with the old structure, this will simply be the root of the module. For gradle-based projects, this is typically the currentModulePath / src / main that needs to be considered. The module root itself is obtained as follows:
 Module module = selectedConfiguration.getConfigurationModule().getModule(); currentModuleFilePath = module.getModuleFilePath(); String currentModulePath = currentModuleFilePath.substring(0, currentModuleFilePath.lastIndexOf(File.separator)); 

Parsing the found AndroidManifest.xml with the same StAX parser, for the package attribute, is already a trivial task.

In fact, the received data ( deviceId and package ) is enough to directly start running adb uninstall . But before that, we will do another, mostly cosmetic, thing. Distinguishing devices by deviceId is not very convenient, so let's try to provide the user with more human-readable ( “ human-readable ?”) Information. For this purpose, execute the following command for each device:
 adb -s <deviceId> shell cat /system/build.prop; 

The result of which will be a long list (in fact, this is an associative array) of various characteristics of the device. We choose only the ones we need, namely:
 ro.product.manufacturer ro.product.model ro.build.version.release ro.build.version.sdk 

As a result, instead of the abstract spell R32CC02G02Z, the user will see the proud: “Samsung Nexus 10 Android 4.3 (API 18)” .

Things are easy, we show the user a modal window with all this good, we get a list of selected devices and, in the order of the live queue, run the coveted adb uninstall :
 Process pr = Runtime.getRuntime().exec(toolPath + File.separator + "adb -s " + device.getSerialNumber() + " uninstall " + packageName); 

It's all.

The source code of the project on GitHub : github.com/Ghedeon/ADB-Uninstall .

Addition:


I would like to mark the users Lucyfer and yole . Thank you guys for good advice.

Source: https://habr.com/ru/post/194514/


All Articles