📜 ⬆️ ⬇️

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

Usually the developer has his favorite tool that is more convenient for him to use than others. However, it so happens that the platform forces developers to pick up a tool that is not as convenient as he would like, or simply does not like something. It so happened that traditionally Android applications are written using Eclipse, since Google decided that they would develop an official plugin, ADT, just for this editor. As a result, those developers who did not use it, willy-nilly, had to master it.

Fortunately, Google also provides a build system that works regardless of the IDE available. And this means that you can configure any editor to work with Android applications. Personally, I prefer to write Java code in the NetBeans IDE and I want to explain how it can be configured for this. There are plugins like nbandroid , but it is not developed regularly by enthusiasts, so it makes sense to take advantage of the flexibility of NetBeans and use the official build system directly from the editor.


Creating a new project


When creating a new project, unfortunately, you will have to do more actions than you could do in Eclipse, but this needs to be done only once. Creating a project is done in three steps:
')
  1. Creating files for assembly from the command line;
  2. Creating a project in the IDE;
  3. Adding additional commands (to taste).

Creating files for assembly

First of all, you need to create a new project via the command line. I will proceed from the assumption that the <Android-SDK>/tools folder has already got into PATH . The project is created by the following command:

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

Just in case, let me explain that the API level is the one with which we will compile the project. That is, if the project as a whole is designed for an API level of 10, but there are some possibilities that are used only on devices with a level of 15 or higher, then you need exactly 15 to set. In AndroidManifest.xml , by the way, this 15 will not light up, there will only be 10 as the minimum required API level.

Suppose that our project is created for Android 4.0.3 (this is level 15) and is called KillerApp. Then you will need to enter the following:

android create project -n KillerApp -t android-15 -p KillerApp -k com.damageinc.killerapp -a MainActivity

After this command, all the files we need are built up in the project folder: configuration files and, most importantly, an assembly file. This is where the command line is finished, and we will not see it again. Now it is necessary to conjure in IDE.

Creating a project in the IDE

  1. On the screen to create a new project in NetBeans, you need the Java Free-Form Project item, with which we will explain the IDE where to get the assembly file.

    1. New Project

  2. Next you need to select the project folder. NetBeans will find the build file itself and figure out what the project is called, so after selecting the folder, you can safely go to the next screen.

    2. Name and Location

  3. And now we need to correctly register the build tasks so that the IDE knows what to run when we go to build the project. Assembly in the system is carried out by the debug task. It looks a bit strange, but the reason for this name is very simple: this task creates a debugging build signed with the appropriate certificate. Accordingly, there is a release task, which we will still get to. The launch of the project in our case means assembly and installation, which means the execution of the install task after the assembly. There is also assigned the task of launch , which is not in the standard system, but we will do it ourselves. Cleaning is, quite expectedly, clean , and you need to test in Android through a separate, test project, so you can easily erase what is in that field.

    3. Build and Run Actions

  4. On the next screen, you need to add the gen folder to the source folders, because it is in this folder that the R.java file will be located.

    4. Source Package Folders

  5. Now we set up code hints. First of all, it is important to uncheck the box for sharing source folders, otherwise the IDE will think that the R file should not be mentioned in the code of our program, since it is in a separate folder. You also need to add the correct Android platform to the list of libraries, in our case it is <Android-SDK>/platforms/android-15/android.jar .

    5. Java Classpath Sources

  6. And finally, the last step is adding the bin/classes folder so that the IDE knows where to look for the compiled code. In principle, this step is not mandatory, and you can safely spit on it. But for the sake of completeness, I will make it so that NetBeans shows which files have been recently modified and not yet compiled.

    6. Project Output


Adding additional commands

In fact, after the last step you can do nothing more. The project is created and is already being assembled. But you can go ahead and make a lot of comforts. In the project folder you should put the custom_rules.xml file , and write in it
ant tasks we need
 <project name="CustomRules"> <target name="release-and-save" depends="release"> <xpath input="AndroidManifest.xml" expression="/manifest/@android:versionName" output="manifest.versionName" default="test"/> <xpath input="AndroidManifest.xml" expression="/manifest/@android:versionCode" output="manifest.versionCode" default="test"/> <copy file="${out.final.file}" tofile="releases/${ant.project.name}-release${manifest.versionCode}-${manifest.versionName}.apk" overwrite="true"/> <copy file="${obfuscate.absolute.dir}/mapping.txt" tofile="releases/mapping-release${manifest.versionCode}.txt" overwrite="true"/> </target> <target name="rebuild-resources" depends="-set-debug-mode, -build-setup, -code-gen" /> <target name="-find-main-activity"> <xpath input="AndroidManifest.xml" expression="/manifest/@package" output="project.app.package" default="test"/> <xpath input="AndroidManifest.xml" expression="/manifest/application/activity[intent-filter/category/@android:name = 'android.intent.category.LAUNCHER'][1]/@android:name" output="project.app.mainactivity" default="test"/> <if> <condition> <matches pattern="\..+|[^\.].*\..*[^\.]" string="${project.app.mainactivity}"/> </condition> <then> <property name="project.app.mainactivity.qualified" value="${project.app.mainactivity}"/> </then> <else> <property name="project.app.mainactivity.qualified" value=".${project.app.mainactivity}"/> </else> </if> <property name="project.app.launcharg" value="-a android.intent.action.MAIN -n ${project.app.package}/${project.app.mainactivity.qualified}"/> </target> <target name="launch" depends="-find-main-activity"> <exec executable="adb"> <arg line="shell am start"/> <arg line="${project.app.launcharg}"/> </exec> </target> </project> 

These three tasks allow us to do some very useful things. rebuild-resources allows you to generate an R file (which in Eclipse, by the way, often disappears somewhere or is not updated on time). launch will give us the opportunity to launch applications, and release-and-save will ensure that when building the final version, it will be saved in a separate folder under the appropriate name along with the ProGuard method map. I also like to add such lines so that after the build a notification is played:

 <target name="-post-build"> <sound> <success source="C:\Windows\Media\Windows Notify.wav"/> </sound> </target> 

Of course, this particular version of sound is suitable only for Windows, for other OS it is worth choosing another file. Now it remains to add these tasks to the context menu in NetBeans . In the project properties on the Build and Run tab, we have already finalized the Run Project item with the launch task at the end. I added the rest of the tasks I just made to the user menu of the context menu:

Build and run

Now in the context menu of the project the whole bunch of commands we need. You can run the emulator or connect a smartphone, run Run and watch how everything is going and start itself. It remains to make the final touches and turn on obfuscation when building the final version, uncommenting the line in the project.properties file :

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

Also in ant.properties it is worth ant.properties the lines for signing the final assemblies :

key.store = < >
key.alias = < >

Now we have a project ready for work.

How does the build system in Android


In fact, there are already two build systems in Android: one is based on ant, and the other is based on Gradle. In this particular case, we use the ant system. The system with Gradle is being developed in parallel with the new editor that replaces Eclipse - Android Studio . I think this build system is useful for a separate article.

Returning to ant, in the project folder are the following files:


The most important file here is, of course, build.xml . Actually, this is just a small tail of the main system, and all it does is loading properties from files with the properties extension and calling the main system located in the SDK itself.

local.properties contains only one property: the location of the folder with the SDK. This file must be added to the list of exceptions of the version control system , because it contains settings specific to a particular machine. For example, on my Windows this file contains the line

sdk.dir=C:\\Android-SDK

In fact, you can create an ANDROID_HOME environment ANDROID_HOME with the contents of a variable from this file and safely send the file to the trash. Above all, do not forget to restart NetBeans after this.

ant.properties have already met ant.properties , there are stored auxiliary variables like the location of the keystore. There is also a project.properties file. After the actions described in the creation of the project, there are only lines about the level of the Android API for which the project is going, and about where to look for the ProGuard configuration file. When we add to the library project, the lines about them will appear in the same place.

Finally, the proguard-project.txt file, which, as the name implies, contains instructions from ProGuard. It is initially empty, but this does not mean that ProGuard will run empty, because the SDK folder already has a pre-recorded configuration (remember the uncommented line about ProGuard?), And here we can specify it. For example, I personally love, among other things, to add lines

-renamesourcefileattribute MyProject
-keepattributes SourceFile,LineNumberTable

They further help to collect error reports, since now there is accurate information about which line of code in the project causes a crash or an exception.

Also build.xml loads the file custom_rules.xml , if it exists, in which we added all the tasks we need. Worth a look at the job again.

 <target name="rebuild-resources" depends="-set-debug-mode, -build-setup, -code-gen" /> 

These lines are simply taken from the SDK build system. Unfortunately, there they are not carried out in a separate task, so I had to do it on my own. It is more interesting to look at the other two tasks:

 <target name="release-and-save" depends="release"> <xpath input="AndroidManifest.xml" expression="/manifest/@android:versionName" output="manifest.versionName" default="test"/> <xpath input="AndroidManifest.xml" expression="/manifest/@android:versionCode" output="manifest.versionCode" default="test"/> <copy file="${out.final.file}" tofile="releases/${ant.project.name}-release${manifest.versionCode}-${manifest.versionName}.apk" overwrite="true"/> <copy file="${obfuscate.absolute.dir}/mapping.txt" tofile="releases/mapping-release${manifest.versionCode}.txt" overwrite="true"/> </target> 

With the help of XPath, the version parameters are acquired here and further with their help file names are generated. In the usual ant, there is no XPath support, so where does it come from? Google’s Android SDK has added its own tools to make it easier to work with applications. Many of their tools come down to running certain files from the SDK, but there are some that make it easier to write build files, such as xpath . Another useful tool, for example, is if , which does exactly what the corresponding construct does in programming languages: performing one or another task depending on the condition.

The second task also uses xpath , this time the task is a bit more complicated:

 <target name="-find-main-activity"> <xpath input="AndroidManifest.xml" expression="/manifest/@package" output="project.app.package" default="test"/> <xpath input="AndroidManifest.xml" expression="/manifest/application/activity[intent-filter/category/@android:name = 'android.intent.category.LAUNCHER'][1]/@android:name" output="project.app.mainactivity" default="test"/> <if> <condition> <matches pattern="\..+|[^\.].*\..*[^\.]" string="${project.app.mainactivity}"/> </condition> <then> <property name="project.app.mainactivity.qualified" value="${project.app.mainactivity}"/> </then> <else> <property name="project.app.mainactivity.qualified" value=".${project.app.mainactivity}"/> </else> </if> <property name="project.app.launcharg" value="-a android.intent.action.MAIN -n ${project.app.package}/${project.app.mainactivity.qualified}"/> </target> <target name="launch" depends="-find-main-activity"> <exec executable="adb"> <arg line="shell am start"/> <arg line="${project.app.launcharg}"/> </exec> </target> 

You need to find the activity that defines the category android.intent.category.LAUNCHER in its intent filter of intentions - this is how Android defines activities that should be shown in the menu. There may be several of them (although this is rare), so the task takes the first one.

There is another snag. Activities are declared in AndroidManifest.xml either by a record with the full name, or only by the name of a class with a dot in front, if the activity lies in the main package. At least that is what the documentation says . The only problem is that Eclipse and other tools allow the dot to drop and just write the name of the activity when it is in the main package. Android tolerates such connivance, but the team running the application is no longer there. We have to add a point when it is not enough. Here the task if , recently mentioned by me, and regular expressions will help us.

There was also a very simple task that reproduces sound. It used one of six hooks that were pulled from the assembly file in the SDK:


Hooks reflect the steps through which the program builds: compilation of libraries, code generation (RenderScript, aidl, R, BuildConfig), project compilation, APK packaging, signature, and zipalign . Accordingly, -pre-build is called before all these actions begin, -pre-compile just before the compilation of the project itself, -post-compile - between compilation and packaging, -post-build - after packaging, but before signing, and -post-build is called at the very end. Well, when -pre-clean is called, I think, is clear from the name.

Instead of conclusion


Today we looked at the most important thing: the creation of the project. Actually, after this project is quite working, you can sit down and scribble code. But we will need to add libraries to the project, debug, and also create tests. All these actions are also great in NetBeans. How this can be done, I will describe in the next part of the article.

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


All Articles