📜 ⬆️ ⬇️

Development for Android in NetBeans IDE without plug-ins. Part 2

We continue the experiment we started on setting up a NetBeans IDE for Android programming. Last time, we managed to create a project in NetBeans, set up an assembly system, and also make an automatic application launch. In addition, we looked a little at how the build system is built from the inside. In the second part of this article, we’ll go ahead and see how you can debug NetBeans, create library projects, add libraries to projects, and work with unit tests.

Debugging


Interestingly, debugging in NetBeans can be done in two ways. The first way will not even require any witchcraft in ant. The second will be a little more difficult to set up, but in some cases it comes in handy, and it’s more like what is in Eclipse.

Method number 1

Before you start doing something, you need to think about a tool called monitor. It is located in the <Android-SDK>/tools folder. As I wrote in the last part of the article, it should already be in the PATH, so you can run directly from the command line or the search string in Windows, but no one, of course, does not interfere and create a shortcut. Those who worked in Eclipse, immediately recognize all the panels in this tool. The most important are logcat and Devices.
')
After the monitor is open, you need to start the application, if it is not already running, and see which port you need to connect to the debugger. The port is written opposite the application. By default, they have an 860x scheme. You can also click on one of the applications to assign port 8700 to it. After that, NetBeans needs to connect to this port via the Attach Debugger command. We select the parameters of Socket Attach, localhost, the required port ... And that's all, then you can safely do debugging.

Attaching a debugger

The button in the panel remembers the newly entered configurations, so the next time you do not even have to enter anything.

Memorized configurations

Separately, I note that monitor is called not only to look at the ports. It also acts as an intermediary in connection with the virtual machine, so that, if it is not running, it will not be possible to connect at random to port 8600.

This debugging method has the advantage of being able to connect and disconnect at any time. This is important, because with the debugger enabled, Dalvik VM starts to slow down noticeably. Sometimes this is not critical, but not always, so the opportunity to get to a certain point of execution in a program without a debugger is sometimes not at all superfluous.

There is another tool that helps to connect the debugger at a certain point. You can, of course, create a breakpoint by condition, but, as I said, with the debugger connected, everything works very well. Therefore, you can insert a call to Debug.waitForDebugger() in the code. As soon as the program reaches this method, it will stop, and execution will continue further only after connecting the debugger.

But sometimes you need to start debugging at the time of launching the program. You can use the same call to the aforementioned method, or you can configure the second way to start debugging in NetBeans.

Method number 2

The second method will act in the same way as in Eclipse: we start debugging, and the application itself starts. After that, it waits for the debugger to connect, and only then continues to run. NetBeans will help us here too. If you try to debug ( CTRL+F5 ), NetBeans will offer to generate an Ant-file, which will tell him how to do it in our project. That is what we need. After that, in the subfolder of the nbproject project, the ide-file-targets.xml , the contents of which need to be replaced with the following:

 <?xml version="1.0" encoding="UTF-8"?> <project basedir=".." name="KillerApp-IDE"> <import file="../build.xml"/> <target name="-load-props"> <property file="nbproject/debug.properties"/> </target> <target name="-check-props"> <fail unless="jpda.host"/> <fail unless="jpda.address"/> <fail unless="jpda.transport"/> </target> <target name="-init" depends="-load-props, -check-props"/> <target name="-launch-monitor"> <if> <condition> <not> <socket server="localhost" port="8700"/> </not> </condition> <then> <exec executable="${android.tools.dir}/monitor${bat}"/> <waitfor maxwait="20" maxwaitunit="second"> <socket server="localhost" port="8700"/> </waitfor> <sleep seconds="2"/> </then> </if> </target> <target name="-launch-debug" depends="-find-main-activity"> <exec executable="adb"> <arg line="shell am start -D"/> <arg line="${project.app.launcharg}"/> </exec> </target> <target name="debug-nb" depends="-init, -launch-monitor, -launch-debug"> <nbjpdaconnect address="${jpda.address}" host="${jpda.host}" name="${ant.project.name}" transport="${jpda.transport}" /> </target> </project> 

The file begins by loading properties from the debug.properties file, which you need to debug.properties into the same folder with the following contents:

 jpda.host=localhost jpda.address=8700 jpda.transport=dt_socket 

Now you can figure out what this file does. The main task here is debug-nb , which NetBeans starts when debugging starts, and it depends on the tasks -init , -launch-monitor and -launch-debug . There -init nothing particularly interesting in -init , the task simply loads and checks the variables from the debug.properties file. But -launch-monitor already more accessible: we need to start the monitor, if it is not already running, and this task just takes on the task. In ant, there is a good task that allows you to see if a program is listening on a specific port or not - a socket . On this basis, it is just possible to determine whether the monitor is running or not. If not, then you need to start it and wait (task wait-for ). After the launch, it is still worth waiting for two seconds in order for the monitor to start accepting connections (the value may have to be adjusted slightly depending on the specific hardware configuration).

After that, you can run the application itself. In the last article, we already did this from ant using the command line. To do this, use the adb shell am start -a android.intent.action.MAIN -n < >/<> command adb shell am start -a android.intent.action.MAIN -n < >/<> . This time we will analyze the command in a bit more detail. adb shell is a command that allows you to work directly from the command line inside Android. am is an activity manager that has a rather impressive set of features; You can read about them in the official documentation . We only need the start command to start the necessary activity, which we specify after the -n key, and the -a key sets the intention, as has probably already become clear.

In the custom_rules.xml file, there is already a task that gives the parameters needed for launching: -find-main-activity . This time we need to start the application in the same way as last time, but with the -D key, so that after launching the application does not immediately continue to work, but first wait for the debugger.

Thus, after all these scams have been completed, the debug-nb already ready to be launched: the monitor is running, the application is running and the debugger is waiting. It remains only to connect it using the job nbjpdaconnect . As the name implies, this task is purely specific to NetBeans.

I myself use the second method much less often than the first, due to the fact that, as I said, when connecting the Dalvik VM debugger, it starts to portray a slowdown, so getting to the debugged site in the application becomes longer. But, if the problem occurs when you start the application, this method is just what you need.

Adding libraries and creating library projects


The library can be a precompiled jar file, or it can be a separate Android project that needs to be compiled before being included in the project. They are connected, respectively, in different ways.

In the case of a precompiled file, there are very few steps:

  1. You need to drop the file in the libs folder of the main project folder.
  2. In the project properties on the Java tab Sources Classpath, you must add the path to the file. In fact, you can not do this, but then the IDE will not tell us about the code from this library, which negates the advantages of using the IDE.

In the case of a library project, everything is a bit more cunning. You can add it with a command (and this is the official way), or you can add a line in the configuration file. For those who love the official way , we need the following command:

android update project -p < > -l < >


Let's try to add for the sake of example the v7 support library appcompat, which Google has done for those who want to see the action bar on versions of Android prior to 3.0. It is not distributed as a precompiled jar file, but as a library project, since there are additional resources. Suppose that it lies in the same folder as our main project.

android update project -p KillerApp -l ../AndroidCompatibilityPackage-v7-appcompat


Everything! You can already compile the project. If we look in the project.properties file, we will find a line in this configuration file.

android.library.reference.1=../AndroidCompatibilityPackage-v7-appcompat


Actually, that's all that team did. In the same way, you can add new libraries without any command, the main thing is not to forget to increase the library number by one: android.library.reference.2 , android.library.reference.3 and so on.

Of course, as with the precompiled file, you need to remember to add on the Java Sources Classpath list the source library folders of the library project mentioned in the project, as well as the libraries that it uses (if we also use them). That is, it is worth adding the src , gen and jar folders in the libs folder of the library project.

What if we want to create our own project? Creating a library project is exactly the same as creating a regular project with the exception that a slightly different command is needed:

android create lib-project -n < > -t android-< API> -p < > -k < >


The main difference is that lib-project is introduced instead of project . In addition, you do not need to specify the name of the main activity, since the library will not have to be run directly. Further creation of the project proceeds in the same way as for a regular project.

Creating projects for tests


As you know, unfortunately, you cannot embed unit tests directly into a project in Android, and you need to create a separate project for this action. Like the creation of a library project, all the steps are very similar to the creation of a regular project, but a bit more nuanced. You will need the following command:

android create test-project -p < > -n < > -m < >


Projects for tests are usually created in a subfolder of the main project, so we will create such a project from the main project folder:

android create test-project -p tests -n KillerAppTest -m ..


You can then continue creating a new project in NetBeans in the same way as in the case of a regular project. But this time we will be able to leave the test item in the third step, when we assign ant tasks to different menu items. But from the Run Project now worth removing the launch and leaving only debug install , since we still have nothing to run here.

Test Project Commands

For a regular project, after that we still added files related to the launch of the application, but this time it does not need anything for us. But what can be done is to add files that will help us debug tests and run them selectively.

First you need to generate a file for additional tasks in NetBeans. We are interested in running separate files, debugging and debugging individual files. All these actions can be generated by pressing CTRL+F6 , CTRL+F5 and CTRL+SHIFT+F5 . After that, you need to nbproject files into the nbproject folder again, just like when adding debugging to a regular project using the second method, only the ide-file-targets.xml will be slightly different. The beginning of the file is the same as in the case of debugging a regular project, so I do not copy the entire file. Those interested can watch it on BitBucket . But then we have other tasks:

 <target depends="-setup" name="run-selected-file-in-src"> <fail unless="run.class">Must set property 'run.class'</fail> <echo level="info">Running tests in ${run.class}...</echo> <run-tests-helper> <extra-instrument-args> <arg value="-e"/> <arg value="class"/> <arg value="${run.class}"/> </extra-instrument-args> </run-tests-helper> </target> <macrodef name="launch-debug-and-connect"> <element name="debugged-class" optional="yes"/> <sequential> <parallel> <run-tests-helper> <extra-instrument-args> <debugged-class/> <arg value="-e"/> <arg value="debug"/> <arg value="true"/> </extra-instrument-args> </run-tests-helper> <sequential> <sleep seconds="5"/> <nbjpdaconnect address="${jpda.address}" host="${jpda.host}" name="${ant.project.name}" transport="${jpda.transport}" /> </sequential> </parallel> </sequential> </macrodef> <target depends="-setup, -init, -launch-monitor" name="debug-selected-file-in-src"> <fail unless="debug.class">Must set property 'debug.class'</fail> <echo level="info">Debugging tests in ${debug.class}...</echo> <launch-debug-and-connect> <debugged-class> <arg value="-e"/> <arg value="class"/> <arg value="${debug.class}"/> </debugged-class> </launch-debug-and-connect> </target> <target depends="-setup, -init, -launch-monitor" name="debug-nb"> <launch-debug-and-connect/> </target> 

The run-selected-file-in-src task is needed to run individual tests. It uses the run-tests-helper macro, which is defined in the Android build system with additional parameters. In fact, all that this macro does is run the adb shell am instrument command with parameters to test the program (yes, this is again the activity manager). We add the -e class < > arguments to the command launch, so the device will not chase all tests indiscriminately, but will focus on a specific file.

Then there are tasks in which we need to perform debugging. In order to do it, you need to start testing first with instructions to wait for the debugger, and then connect. But there is a small snag: the launch of testing happens with blocking, and we need to start another task. We will save the task parallel , which runs different tasks together. The result is designed as a macro, so that you can adjust with what parameters the test is called. Accordingly, our debugging tasks just call it, with additional parameters, if needed.

Total


Now we can sum up what we have done. In total, a very good amount of possibilities turned out:


Projects are created by a single command from the command line and a couple of additional files that are universal for each project, so everything is pretty simple in terms of effort. What we lack compared to what we already have in Eclipse or Android Studio:


Editing XML files is not so critical, but, of course, it’s pretty sad to edit the interface without a WYSIWYG editor. Therefore, I personally import the project into Eclipse and edit the interface there when required.

I also want to say a few words about the applicability of such tools. In the comments to the previous article, such questions arose, so let me remind you once again: this is an experiment. If there is an official build system via ant, independent of the IDE, then it was difficult for me to hold onto and not try using it to configure a tool that was not originally designed to work with Android.

Moreover, in fact, it’s not necessary to use NetBeans to use this system. After setting up the project, you can simply type in the command line, for example, ant debug install launch , to build and run the project. And, unlike a self-made script build , it will be a full build - exactly the same as Eclipse does with ADT: with the generation of interfaces from AIDL, BuildConfig, RenderScript, zipalign, ProGuard and all the rest. As for using it to program in NetBeans, this is, of course, very much for the amateur. But, in any case, I personally was very interested in conducting this experiment, and I hope that it was interesting for others to read about it.

Couple of links


  1. All files on BitBucket
  2. Development for Android in NetBeans IDE without plug-ins. Part 1

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


All Articles