MyTetra Share
Делитесь знаниями!
HelloWorld для Android в блокноте
02.04.2017
08:41
Текстовые метки: Android, Java
Раздел: Android - Ресурсы - Сборки APK

Пишем, собираем и запускаем HelloWorld для Android в блокноте tutorial

Разработка под Android*, Java*



Когда я начал изучать Android, захотелось полностью написать и скомпилировать Android-приложение вручную — без использования IDE. Однако эта задача оказалась непростой и заняла у меня довольно много времени. Но как оказалось — такой подход принёс
большую пользу и прояснил многие тонкости, которые скрывают IDE.

По-сути эта статья является переводом и переработкой статьи
Building Android programs on the command line под современные на данный момент JDK (7) и Android SDK (API level 19). Кроме того, я многое упростил и добавил кое-что от себя.

Используя только блокнот, мы напишем совсем маленькое учебное Android-приложение. А затем скомпилируем его, соберём и запустим на устройстве — и всё через командную строку. Заинтересовало? Тогда прошу.

Вступление


Я был поражён, насколько сложным и запутанным является шаблонное приложение в android studio. Оно просто нагромождено ресурсами. И в меньшей степени — кодом и скриптами. Хотя всё что оно должно делать — это выводить на экран HelloWorld! Кроме того, в книгах и руководствах, которые я просмотрел, объясняется, как с помощью диалоговых окон создать IDEA-шный или эклипсовый HelloWorld — и от него уже идёт дальнейшее повествование. А что происходит «под капотом» — остаётся только гадать.

Долгие поиски были почти безрезультатны — на русском языке статей по данной теме я не нашёл, а на английском — была устаревшая информация и кое-что пришлось дорабатывать напильником, гуляя по
stackowerflow и документации. Когда я разобрался, то решил восполнить пробел — вдруг кому-то пригодится? Собственно, так и появилась эта статья.

Мы создадим свой шаблонный проект, который идеально использовать для обучения. Там не будет ничего лишнего, только всё самое необходимое. А потом детально разберём, как его собрать и запустить на вашем Android-устройстве. В конце статьи будет ссылка на скачивание архива с итоговым проектом — если возникнут какие-то вопросы — можете свериться с ним.

Таким образом, вы будете на 100% знать и понимать состав вашего проекта и процесс его сборки. Хотя этот тестовый проект предназначен для обучения, при небольшой доработке его можно будет использовать как
прочный фундамент для ваших реальных проектов.

Подготовка


Для начала у вас должен быть установлен
JDK 7 и android SDK. Последний кстати нужно чуточку настроить после установки.

Главное требование перед прочтением этой статьи — кроме установленного софта вы должны уже уметь запускать на вашем девайсе тот Helloworld, который поставляется вместе с Eclipse или Android Studio. Т.е. у вас должен быть настроен драйвер usb, включена отладка по usb на вашем девайсе и т.д… Или же создан и настроен эмулятор. Это совсем элементарные вещи, и их рассмотрение выходит за рамки данной статьи — в сети достаточно информации. Кстати прочитать пару глав из книг тоже будет не лишним — хотя бы понимать, как устроен манифест, ресурсы, да и вообще основы языка Java. А в этой статье я опишу то, о чём книги молчат.

Написание проекта


Для начала, создайте некоторую папку, где будет ваш проект. Назовём её mytestapp. В ней создайте ещё 4 папки —
bin,obj,res и src.

Создайте пустой текстовый файл и измените его имя на
AndroidManifest.xml. Если вы начинающий пользователь Windows, вам нужно включить показ расширений, иначе файл будет по-прежнему текстовым.

Добавьте в него следующее:

<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>


Тут всё просто. Мы намерены сделать приложение с именем TestApp, которое при старте запускает класс MainActivity. Осталось только написать этот небольшой класс — и приложение готово. Если нужно — отредактируйте в теге uses-sdk свойство android:targetSdkVersion — поставьте ту версию, которая у вас.

Далее — создадим простейший ресурс — строку
Hello test app. Вообще-то мы могли обойтись и без ресурса, вставив эту строку прямо в Java код. Но некоторые шаги сборки работают с ресурсами, и чтобы увидеть интересные моменты — мы всё-таки поработаем с ними.

Давайте создадим в папке
res папку values. Все ресурсы следует разбивать по папкам. Далее — в ней создадим пустой файл strings.xml. а в нём напишем

<resources>

<string name="hello">Hello test app!</string>

</resources>


Вот и все ресурсы, нам необходимые. Просто, не так ли? Далее создадим внутри
src папку com, в ней папку example, потом ещё ниже по иерархии папку testapp — а там уже наш класс MainActivity.java. Добавим туда код

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);

}

}


Структура каталогов должна получится такая

│ AndroidManifest.xml

├───bin

├───obj

├───res

│ └───values

│ strings.xml

└───src

└───com

└───example

└───testapp

MainActivity.java



И это собственно всё, что нам было нужно для простейшего проекта. Для сравнения —

HelloWorld от android studio


Сборка


Теперь же подходим к самому важному и сложному этапу. Мы будем много работать с командной строкой, поэтому рекомендую вам все команды, данные здесь, записывать в один файл и назвать его
comp.bat. В конце файла после команд можете добавить pause, чтобы был виден результат и ошибки — если таковые возникнут.

Подготовка путей


Первое, что мы сделаем для удобства и краткости — создадим специальные переменные, в которых будем хранить пути. Для начала — определим наши основные директории. Вам нужно заменить пути к JDK и Android SDK на те, которые у вас.

set JAVA_HOME=C:\prog\sdk\jdk\1.7

set ANDROID_HOME=C:\prog\sdk\android-studio\sdk

set DEV_HOME=%CD%



Далее — пути непосредственно к программам. Я рекомендую вам просмотреть каталоги ваших SDK и убедится в том, что всё на месте. Также подкорректировать версии, которые присутствуют в путях.

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



Между прочим, в более старых версиях утилита aapt находилась в platform-tools — и я не исключаю что она и\или другие могут слинять куда-нибудь ещё. Так что будьте внимательны. Если вы всё правильно сверите сейчас — то остальная часть статьи должна пройти гладко.

И ещё — в пару переменных забьём наши пакеты и классы. Если заходите их сменить — вам не придётся бегать по коду — все настройки вначале.

set PACKAGE_PATH=com/example/testapp

set PACKAGE=com.example.testapp

set MAIN_CLASS=MainActivity



Подготовка к компиляции


А теперь самое интересное. Помните, как классические Java-программы компилируются и запускаются в 2 строчки? Здесь мы используем тот же самый
javac, однако кроме него нам предстоит использовать ещё много утилит.

Для начала спрошу — а вы никогда не задумывались, как работает загадочный класс R? Собственно меня он сперва смутил из-за его сверхъестественных возможностей. Как на этапе компиляции можно через поля класса обращаться к XML-файлам в других каталогах? Я предположил, что тут орудует прекомпилятор — так оно и оказалось.

Собственно, есть специальная утилита AAPT — она проходится по каталогам ваших ресурсов и создаёт тот самый R.java. Оказывается, всё очень даже просто — это просто класс, в составе которого другие статические вложенные классы с целочисленными константами. И всё! Он выглядит примерно так

R.java


Теперь давайте создадим его у вас. Для этого используем следующие команды:

call %AAPT_PATH% package -f -m -S %DEV_HOME%/res -J %DEV_HOME%/src -M %DEV_HOME%/AndroidManifest.xml -I %ANDROID_JAR%


Давайте разберёмся, что к чему. AAPT — Android Asset Packaging Tool — буквально «упаковщик андроид-имущества». Его опции:

  • package — говорит, что нам нужно именно упаковать ресурсы (а не добавить или удалить)
  • -f — перезапись существующего R.java, если таковой имеется
  • -m — разместить R.java в надлежащих пакетах, а не в корне указанного в -J пути
  • -S — после этой опции мы указываем каталог с ресурсами
  • -J — после этой опции мы указываем куда сохранить получившийся R.java
  • -I — после этой опции мы указываем путь к подключаемой библиотеке — включаем android.jar


После его выполнения в каталоге src должен появится тот самый файл R.java. Проверьте.

Теперь в нашем проекте нет никакой магии и он полностью синтаксически корректен для обычного Java-компилятора. Давайте скомпилируем его.

call %JAVA_HOME%/bin/javac -d %DEV_HOME%/obj -cp %ANDROID_JAR% -sourcepath %DEV_HOME%/src %DEV_HOME%/src/%PACKAGE_PATH%/*.java


Если вы ранее работали с java, то понять эту строчку для вас не составит труда. Однако я всё-таки объясню, что к чему:

  • -d — куда поместить итоговые пакеты и *.class-файлы
  • -cp — classpatch — укажем путь к библиотеке android.jar
  • -sourcepath — пути, где находятся (или могут находится) наши *.java файлы


После выполнения в папке obj должны находится пакеты с нашими классами в виде байт-кода (*.class). Но вот ведь незадача — виртуальная машина андроида с ним не совместима! Но так было задумано и на это есть причины. А мы используем конвертер, который делает из class-файлов dex-файл, понятный для нашего зелёного R2D2.

call %DX_PATH% --dex --output=%DEV_HOME%/bin/classes.dex %DEV_HOME%/obj


Опция
--dex указывает на то, что нам нужно преобразовать из *.class в *.dex. Затем после опции --output мы задаём путь к итоговому файлу classes.dex. И последний аргумент в этой команде — путь непосредственно к пакетам, содержащим *.class файлы

Убедитесь в том, что в папке bin находится наш classes.dex. Теперь осталось только упаковать его вместе с ресурсами в APK-файл. Сделаем это:

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


Здесь опции аналогичны тем, которые мы использовали при создании
R.java:

  • package — говорит, что нам нужно именно упаковать ресурсы (а не добавить или удалить)
  • -f — перезапись существующего AndroidTest.unsigned.apk, если таковой имеется
  • -M — после этой опции мы указываем путь к файлу манифеста
  • -S — после этой опции мы указываем каталог с ресурсами
  • -I — после этой опции мы указываем путь к подключаемой библиотеке — включаем android.jar
  • -F — после этой опции мы указываем куда сохранить получившийся AndroidTest.unsigned.apk
  • последний аргумент — путь к папке с dex — файлами


В папке bin теперь должен появится
AndroidTest.unsigned.apk. И мы назвали его не просто так! У него нет цифровой подписи. Андроид запрещает устанавливать и запускать приложения без подписи. Но создать её не так-то трудно, как может показаться на первый взгляд

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


Собственно, эти строчки запускают 2 Java-утилиты, которые не имеют никакого отношения к Android SDK — но они необходимы. Первая создаёт файл AndroidTest.keystore (проверьте его наличие), а вторая — этот файл соединяет с
AndroidTest.unsigned.apk. Получается файл AndroidTest.signed.apk. Вот такой дикий крафт файлов. Но однажды создав bat-скрипт запускайте его — и он будет делать всё это в автоматическом режиме.

Я думаю, не стоит тратить время на детальный разбор опций этих утилит в пределах данной статьи. Просто нужно уловить суть — они берут
AndroidTest.unsigned.apk, подписывают его файлом AndroidTest.keystore и сохраняют в AndroidTest.signed.apk. Если есть желание, можете почитать в документации.

У вас, скорее всего, будет предупреждение "
Warning: No -tsa or -tsacert is provided and this jar...", но не обращайте внимание.

Запуск


Теперь, когда мы наконец собрали наш apk-файл — можем его запустить. Подключите по usb ваше устройство, или же запустите эмулятор. А затем выполните

call %ADB% uninstall %PACKAGE%

call %ADB% install %DEV_HOME%/bin/AndroidTest.signed.apk

call %ADB% shell am start %PACKAGE%/%PACKAGE%.%MAIN_CLASS%


Собственно, первая строчка удаляет программку, если она уже там есть. Для повторных запусков пригодится. Вторая — устанавливает APK на ваш девайс или эмулятор. Третья же — запускает. Давайте более подробно разберём её аргументы:

  • shell — мы хотим выполнить некоторые команды на нашем девайсе
  • am — используем для выполнения команд activity manager
  • start — мы хотим запустить некоторое Activity
  • имя пакета и полное имя класса (включая пакет), которые мы стартуем


Если всё прошло удачно, вы увидите что-то вроде этого:


Заключение


После сборки всех файлов дерево каталогов должно быть примерно таким.

│ 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



Теперь вы можете наглядно увидеть и понять, как происходит сборка андроид-приложения на более низком уровне. Когда будете использовать IDE — если сборка вдруг пойдёт не так (а такое часто бывает) — сможете вырулить ситуацию как надо. Также обратите внимание на то, что итоговый apk-файл
занимает всего около 4 килобайт.

Выкладываю архив проекта (Нажимайте Файл-Скачать). Обратите внимание, что я добавил туда ещё один маленький скрипт — clear.bat. Он удаляет все созданные при сборке файлы. И поставил его запуск на начало comp.bat. Также добавил комментарии после Rem — по шагам.

Таким образом, скрипт производит
полную очистку и пересборку проекта, включая подпись, а также удаление его на устройстве, установку и запуск.

Прикрепленные файлы:
 
MyTetra Share v.0.52
Яндекс индекс цитирования