πŸ“œ ⬆️ ⬇️

We write, collect and run HelloWorld for Android in Notepad



When I started learning Android, I wanted to completely write and compile an Android application manually - without using an IDE. However, this task proved to be difficult and took me quite a lot of time. But as it turned out - this approach has brought great benefits and clarified many subtleties that hide the IDE.

In fact, this article is a translation and revision of the article Building Android programs on the command line under the currently current JDK (7) and Android SDK (API level 19) . In addition, I simplified a lot and added something from myself.
')
Using only a notebook, we will write a very small educational Android application. And then compile it, build and run on the device - and all through the command line. Interested? Then I ask.

Introduction


I was amazed at how complex and confusing the sample application in android studio is. It is simply piled up with resources. And to a lesser extent - code and scripts. Although all it has to do is display HelloWorld! In addition, the books and manuals that I have reviewed explain how to create an IDEA or eclipse HelloWorld using dialog boxes - and further narrative is already coming from it. And what happens "under the hood" - it remains only to guess.

Long searches were almost unsuccessful - I did not find any articles on this topic in Russian, but in English there was outdated information and some things had to be edited by file, walking along stackflowflow and documentation . When I figured it out, I decided to fill the gap - what if someone came in handy? Actually, this is how the article appeared.

We will create our own template project, which is ideal for training. There will be nothing superfluous, only all the most necessary. And then we will analyze in detail how to assemble and run it on your Android device. At the end of the article there will be a link to download the archive with the final project - if you have any questions, you can check it out.

Thus, you will be 100% aware and understand the composition of your project and the process of its assembly. Although this test project is designed for training, with a little refinement it can be used as a solid foundation for your real projects.

Training


First you need to have JDK 7 and android SDK installed. The last way you need to configure a little after installation.

The main requirement before reading this article is that in addition to the installed software, you should already be able to run the Helloworld that comes with Eclipse or Android Studio on your device. Those. you must have a usb driver configured, usb debugging enabled on your device, etc ... Or, an emulator is created and configured. These are very basic things, and their consideration is beyond the scope of this article - there is enough information on the net. By the way, reading a couple of chapters from books will also not be superfluous - at least to understand how the manifest works, resources, and indeed the basics of the Java language. And in this article I will describe what the books are silent about.

Writing a project


To get started, create some folder where your project will be. Let's call it mytestapp. In it, create 4 more folders - bin , obj , res and src .

Create an empty text file and change its name to AndroidManifest.xml . If you are a novice user of Windows, you need to enable the display of extensions , otherwise the file will still be text.

Add the following to it:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.testapp"> <uses-sdk android:targetSdkVersion="19" /> <application android:label="TestApp"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

It's simple. We intend to make an application named TestApp, which at startup starts the MainActivity class. It remains only to write this small class - and the application is ready. If necessary, edit the android: targetSdkVersion property in the uses-sdk tag β€” install the version that you have.

Next - create a simple resource - the string Hello test app . In fact, we could do without a resource by inserting this line directly into Java code. But some assembly steps work with resources, and in order to see interesting moments we will work with them.

Let's create in the res folder the values folder. All resources should be divided into folders. Next, create an empty strings.xml file in it. and we will write in it
 <resources> <string name="hello">Hello test app!</string> </resources> 

That's all the resources we need. Simple, isn't it? Next, we will create a com folder inside src , an example folder in it, then a testapp folder even lower down in the hierarchy - and then our class is MainActivity.java . Add there code
 package com.example.testapp; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView textView = new TextView(this); textView.setText(getString(R.string.hello)); setContentView(textView); } } 

The directory structure should get this
 β”‚ AndroidManifest.xml β”œβ”€β”€β”€bin β”œβ”€β”€β”€obj β”œβ”€β”€β”€res β”‚ └───values β”‚ strings.xml β”‚ └───src └───com └───example └───testapp MainActivity.java 

And this is actually all that we needed for the simplest project. For comparison -
HelloWorld from android studio
 β”‚ .gitignore β”‚ AndroidStudioHWProject.iml β”‚ build.gradle β”‚ gradlew β”‚ gradlew.bat β”‚ local.properties β”‚ settings.gradle β”‚ β”œβ”€β”€β”€.gradle β”‚ └───1.8 β”‚ └───taskArtifacts β”‚ cache.properties β”‚ cache.properties.lock β”‚ fileHashes.bin β”‚ fileSnapshots.bin β”‚ outputFileStates.bin β”‚ taskArtifacts.bin β”‚ β”œβ”€β”€β”€.idea β”‚ β”‚ .name β”‚ β”‚ compiler.xml β”‚ β”‚ encodings.xml β”‚ β”‚ gradle.xml β”‚ β”‚ misc.xml β”‚ β”‚ modules.xml β”‚ β”‚ vcs.xml β”‚ β”‚ workspace.xml β”‚ β”‚ β”‚ β”œβ”€β”€β”€copyright β”‚ β”‚ profiles_settings.xml β”‚ β”‚ β”‚ β”œβ”€β”€β”€libraries β”‚ β”‚ ComAndroidSupportAppcompatV71901_aar.xml β”‚ β”‚ support_v4_19_0_1.xml β”‚ β”‚ β”‚ └───scopes β”‚ scope_settings.xml β”‚ β”œβ”€β”€β”€AndroidStudioHW β”‚ β”‚ .gitignore β”‚ β”‚ AndroidStudioHW.iml β”‚ β”‚ build.gradle β”‚ β”‚ β”‚ β”œβ”€β”€β”€build β”‚ └───src β”‚ └───main β”‚ β”‚ AndroidManifest.xml β”‚ β”‚ β”‚ β”œβ”€β”€β”€java β”‚ β”‚ └───com β”‚ β”‚ └───example β”‚ β”‚ └───androidstudiohw β”‚ β”‚ MainActivity.java β”‚ β”‚ β”‚ └───res β”‚ β”œβ”€β”€β”€drawable-hdpi β”‚ β”‚ ic_launcher.png β”‚ β”‚ β”‚ β”œβ”€β”€β”€drawable-mdpi β”‚ β”‚ ic_launcher.png β”‚ β”‚ β”‚ β”œβ”€β”€β”€drawable-xhdpi β”‚ β”‚ ic_launcher.png β”‚ β”‚ β”‚ β”œβ”€β”€β”€drawable-xxhdpi β”‚ β”‚ ic_launcher.png β”‚ β”‚ β”‚ β”œβ”€β”€β”€layout β”‚ β”‚ activity_main.xml β”‚ β”‚ fragment_main.xml β”‚ β”‚ β”‚ β”œβ”€β”€β”€menu β”‚ β”‚ main.xml β”‚ β”‚ β”‚ β”œβ”€β”€β”€values β”‚ β”‚ dimens.xml β”‚ β”‚ strings.xml β”‚ β”‚ styles.xml β”‚ β”‚ β”‚ └───values-w820dp β”‚ dimens.xml β”‚ └───gradle └───wrapper gradle-wrapper.jar gradle-wrapper.properties 

Actually, automation through gradle, work with git and IDE are very important things, but at the stage of learning Android I would really like to abstract from them .

Assembly


Now we come to the most important and difficult stage. We will work a lot with the command line, so I recommend that you write all the commands given here into one file and name it comp.bat . At the end of the file after the commands, you can add pause so that the result and errors can be seen - if any.

Preparation of ways

The first thing we will do for convenience and brevity is to create special variables in which we will store paths. First of all, let's define our main directories. You need to replace the paths to the JDK and Android SDK with the ones you have.
 set JAVA_HOME=C:\prog\sdk\jdk\1.7 set ANDROID_HOME=C:\prog\sdk\android-studio\sdk set DEV_HOME=%CD% 

Next - the path directly to the programs. I recommend that you browse the catalogs of your SDK and make sure that everything is in place. Also correct the versions that are present in the paths.
 set AAPT_PATH=%ANDROID_HOME%/build-tools/19.0.1/aapt.exe set DX_PATH=%ANDROID_HOME%/build-tools/19.0.1/dx.bat set ANDROID_JAR=%ANDROID_HOME%/platforms/android-19/android.jar set ADB=%ANDROID_HOME%/platform-tools/adb.exe 

By the way, in older versions, the aapt utility was in platform-tools - and I do not rule out that it and / or others can slip away somewhere else. So be careful. If you check everything right now, then the rest of the article should go smoothly.

And yet - in a couple of variables let's score our packages and classes. If you go to change them - you do not have to run on the code - all the settings at the beginning.
 set PACKAGE_PATH=com/example/testapp set PACKAGE=com.example.testapp set MAIN_CLASS=MainActivity 

Preparing to compile

And now the fun part. Remember how classic Java programs compile and run in 2 lines? Here we use the same javac , but besides it we still have to use many more utilities.

To begin, I will ask - have you ever wondered how the mysterious class R works? Actually he confused me at first because of his supernatural capabilities. How can one at a compilation stage access the XML files in other directories through the class fields? I assumed that the precompiler was operating there - it turned out that way.

Actually, there is a special utility AAPT - it goes through the directories of your resources and creates the very R.java. It turns out that everything is very simple - it's just a class, which includes other static nested classes with integer constants. And that's it! It looks like this
R.java
 /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.example.testapp; public final class R { public static final class attr { } public static final class string { public static final int hello=0x7f020000; } } 


Now let's create it with you. To do this, use the following commands:
 call %AAPT_PATH% package -f -m -S %DEV_HOME%/res -J %DEV_HOME%/src -M %DEV_HOME%/AndroidManifest.xml -I %ANDROID_JAR% 

Let's figure out what's what. AAPT - Android Asset Packaging Tool - literally "packer android property". Its options are:

After its execution, the same R.java file should appear in the src directory. Check it out.

Now there is no magic in our project and it is completely syntactically correct for a regular Java compiler. Let's compile it.
 call %JAVA_HOME%/bin/javac -d %DEV_HOME%/obj -cp %ANDROID_JAR% -sourcepath %DEV_HOME%/src %DEV_HOME%/src/%PACKAGE_PATH%/*.java 

If you have previously worked with java, then understand this line is not difficult for you. However, I still explain what's what:

After execution, the obj folder should contain packages with our classes in bytecode (* .class). But after all, bad luck - the android virtual machine is not compatible with it! But it was conceived and there are reasons for it. And we use a converter that makes a dex file from class files that is understandable for our green R2D2.
 call %DX_PATH% --dex --output=%DEV_HOME%/bin/classes.dex %DEV_HOME%/obj 

The option --dex indicates that we need to convert from * .class to * .dex. Then, after the --output option, we set the path to the resulting classes.dex file. And the last argument in this command is the path directly to packages containing * .class files.

Make sure our classes.dex is in the bin folder. Now you just have to pack it together with the resources in the APK file. Let's do it:
 call %AAPT_PATH% package -f -M %DEV_HOME%/AndroidManifest.xml -S %DEV_HOME%/res -I %ANDROID_JAR% -F %DEV_HOME%/bin/AndroidTest.unsigned.apk %DEV_HOME%/bin 

Here the options are similar to those we used when creating R.java :

AndroidTest.unsigned.apk should now appear in the bin folder. And we called it for a reason! He does not have a digital signature. Android prohibits install and run applications without a signature. But creating it is not as difficult as it may seem at first glance.
 call %JAVA_HOME%/bin/keytool -genkey -validity 10000 -dname "CN=AndroidDebug, O=Android, C=US" -keystore %DEV_HOME%/AndroidTest.keystore -storepass android -keypass android -alias androiddebugkey -keyalg RSA -v -keysize 2048 call %JAVA_HOME%/bin/jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore %DEV_HOME%/AndroidTest.keystore -storepass android -keypass android -signedjar %DEV_HOME%/bin/AndroidTest.signed.apk %DEV_HOME%/bin/AndroidTest.unsigned.apk androiddebugkey 

Actually, these lines launch 2 Java utilities that have nothing to do with the Android SDK - but they are necessary. The first one creates the AndroidTest.keystore file (check its availability), and the second one - this file connects to AndroidTest.unsigned.apk . It turns out the file AndroidTest.signed.apk . Here is such a wild craft files. But once you create a bat-script, run it - and it will do it all automatically.

I think it is not worth spending time on a detailed analysis of the options of these utilities within this article. You just need to grasp the point - they take AndroidTest.unsigned.apk , sign it with the AndroidTest.keystore file and save to AndroidTest.signed.apk . If you wish, you can read in the documentation .

You will most likely have the warning " Warning: No -tsa or -tsacert is provided and this jar ... ", but do not pay attention.

Launch

Now that we have finally compiled our apk-file, we can run it. Connect usb to your device, or run the emulator. And then do
 call %ADB% uninstall %PACKAGE% call %ADB% install %DEV_HOME%/bin/AndroidTest.signed.apk call %ADB% shell am start %PACKAGE%/%PACKAGE%.%MAIN_CLASS% 

Actually, the first line removes the program, if it is already there. For re-launches useful. The second - installs the APK on your device or emulator. The third one runs. Let's take a closer look at her arguments:

If everything went well, you will see something like this:


Conclusion


After all the files are assembled, the directory tree should look something like this.
 β”‚ AndroidManifest.xml β”‚ AndroidTest.keystore β”‚ comp.bat β”‚ β”œβ”€β”€β”€bin β”‚ AndroidTest.signed.apk β”‚ AndroidTest.unsigned.apk β”‚ classes.dex β”‚ β”œβ”€β”€β”€obj β”‚ └───com β”‚ └───example β”‚ └───testapp β”‚ MainActivity.class β”‚ R$attr.class β”‚ R$string.class β”‚ R.class β”‚ β”œβ”€β”€β”€res β”‚ └───values β”‚ strings.xml β”‚ └───src └───com └───example └───testapp MainActivity.java R.java 

Now you can visually see and understand how the assembly of the android application occurs at a lower level. When you use IDE - if the assembly suddenly goes wrong (and this often happens) - you can get the situation right. Also note that the final apk-file takes only about 4 kilobytes .

I post the project archive (Click File-Download). Please note that I added another small script there - clear.bat. It deletes all files created during the assembly. And put his launch on top of comp.bat. Also added comments after Rem - in steps.

Thus, the script produces a complete cleanup and reassembly of the project , including the signature, as well as its removal on the device, installation and launch.

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


All Articles