
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/releasesInstallation:
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:
- To use one debug key by all team members, then, from the point of view of the system, everything will look as if you are working on one computer.
- A self-written script and, preferably, smart enough not to ask you about the package name.
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.
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 .
NoteInitially, 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:
- For logs and various messages addressed to the user,
Notifications.Bus.notify(<notification>)
. Depending on the user settings, the message will appear in one or several places of the user interface: Event Log, Balloon, Sticky Balloon, Tool window balloon . Either will not appear at all. - In order to interact with the user, so that your add-ins look organic, it’s better to use not bare Swing , but the components that IntelliJ IDEA offers. In particular, I used the Dialog Wrapper from this set.
- An important unrealized point for me is the collection of statistics, at least for failures in the plug-in. At the moment, there is a curious situation when, in response to the crash of the IDEA plug-in, it offers to send a bug report to Google. I would be grateful for the tip-off, if someone knows tools like Crashlytics , but only for Swing applications.
I would like to mark the users
Lucyfer and
yole . Thank you guys for good advice.