C языковая программа
Однако для Android официальный способ написать Hello World — запустить Android Studio, использовать его мастер для создания нового проекта, а затем автоматически сгенерировать и собрать приложение за считанные минуты.
Это, конечно, для удобства разработчиков, но это усложняет жизнь людям, которые хотят знать, что произошло. Что случилось? Какие из следующих файлов действительно необходимы для Hello World?
Может быть, это и есть тот управляющий, с которым я общаюсь (хорошее качество программистов для своих программ), но я не думаю, что не понимаю, как создавать свои собственные программы.
Ниже приведены инструкции о том, как вручную создать приложение Android из командной строки. Эти инструкции предназначены для Linux, но их легко адаптировать к Mac или Windows. Полный исходный код и скрипт сборки можно найти в command_line_android.tar.gz.
Установить инструменты разработки
Приложения Android обычно пишутся на Java, поэтому для их создания требуется Java Development Kit (JDK). Текущая версия инструмента Android требует Java 8здесьСкачайте, распакуйте и поместите его в мой PATH следующим образом:
tar zxf jdk-8u112-linux-x64.tar.gz export JAVA_HOME=$ /jdk1.8.0_112 export PATH=$ /bin:$PATH
Специальные инструменты для Android предоставляются в комплекте для разработки программного обеспечения Android (SDK). Обычно он устанавливается при установке Android Studio, но мы также можем установить его самостоятельно (см. «Страница загрузки Android Studio»).Получить инструменты командной строки»раздел):
curl -O https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz tar zxf android-sdk_r24.4.1-linux.tgz
К сожалению, этот файл не содержит всего, что нам нужно, как описано в SDK Readme.txt:
Архив Android SDK изначально содержит только базовые инструменты SDK. Не включает платформу Android или сторонние библиотеки.
На самом деле, он даже не имеет всех инструментов, необходимых для разработки приложений.
Чтобы начать разработку приложений, необходимо установить инструменты Platform и хотя бы одну версию платформы Android и использовать SDK Manager.
Нам нужны инструменты сборки (для aapt dx и apksigner), платформа Android для позиционирования (я буду использовать версию 16) и инструменты платформы (для adb).
Мы можем установить их напрямую (имя файла находится вrepository-11.xmlНайдено) вместо использования SDK Manager, как указано выше:
curl -O https://dl.google.com/android/repository/build-tools_r25-linux.zip unzip build-tools_r25-linux.zip mkdir android-sdk-linux/build-tools mv android-7.1.1 android-sdk-linux/build-tools/25.0.0 curl -O https://dl.google.com/android/repository/android-16_r05.zip unzip android-16_r05.zip mv android-4.1.2 android-sdk-linux/platforms/android-16 curl -O https://dl.google.com/android/repository/platform-tools_r25-linux.zip unzip platform-tools_r25-linux.zip -d android-sdk-linux/
The Hello World Program
Наша программа Hello World содержит три файла: манифест приложения, макет и действия.
Список приложений показан ниже (AndroidManifest.xml). Он указывает имя приложения, API Android и т. Д., На который он нацелен. Элемент apect -filter устанавливает MainActivity в качестве главной точки входа в программу.
manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.hanshq.hello" versionCode="1" versionName="0.1"> uses-sdk android:minSdkVersion="16"/> application android:label="Hello"> 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>
Ниже приведен файл макета (res / layout / activity_main.xml). Он определяет элементы пользовательского интерфейса, используемые в нашей программе.
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/my_text"/> LinearLayout>
Наконец, действие реализовано следующим образом: (java / net / hanshq / hello / MainActivity.java)
package net.hanshq.hello; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView text = (TextView)findViewById(R.id.my_text); text.setText("Hello, world!"); > >
Building
Мы будем использовать переменные оболочки для более удобной ссылки на SDK, который мы установили ранее. Все артефакты сборки будут помещены в подкаталоги каталога сборки, который мы создали здесь.
SDK="$ /android-sdk-linux" BUILD_TOOLS="$ /build-tools/25.0.0" PLATFORM="$ /platforms/android-16" mkdir -p build/gen build/obj build/apk
Первым шагом сборки является создание файла R.java, который используется для ссылки на ресурсы (такие как R.id.my_text выше). Это делается с помощью инструмента упаковки активов Android, aapt:
"$ /aapt" package -f -m -J build/gen/ -S res \ -M AndroidManifest.xml -I "$ /android.jar"
Он создаст сборку / gen / net / hanshq / hello / R.java.
Флаг -f заставляет aapt перезаписывать любые существующие выходные файлы, -m заставляет его создавать каталог пакетов в выходном каталоге, а -J заставляет его генерировать файл R.java и устанавливать выходной каталог. -S указывает каталог ресурсов, -M определяет список, -I добавляет файл platform.jar как «включаемый файл».
Теперь, когда весь код Java готов, мы можем скомпилировать его с помощью javac:
javac -source 1.7 -target 1.7 -bootclasspath "$ /jre/lib/rt.jar" \ -classpath "$ /android.jar" -d build/obj \ build/gen/net/hanshq/hello/R.java java/net/hanshq/hello/MainActivity.java
(1.7 и -bootclasspath используются для передачи 7-байтового кода Java, чего ожидают инструменты Android, хотя используется версия 8 JDK.)
Компилятор Java создает файл .class, содержащий байт-код виртуальной машины Java. Затем вы должны использовать инструмент dx, чтобы преобразовать его в байт-код Dalvik:
"$ /dx" --dex --output=build/apk/classes.dex build/obj/
Существует новый набор инструментов Android,jack , Вы можете напрямую скомпилировать код Java в байт-код Dalvik. Может быть, это будет способ работы в будущем. )
Затем мы снова используем инструмент aapt, чтобы упаковать содержимое каталога build / apk /, а также манифест и ресурсы в файл пакета приложения Android (APK):
"$ /aapt" package -f -M AndroidManifest.xml -S res/ \ -I "$ /android.jar" \ -F build/Hello.unsigned.apk build/apk/
Приложение теперь собрано, но файл APK необходимо подписать, прежде чем разрешить запуск любого устройства, даже в режиме отладки. Если мы хотим опубликовать его в Play Store, нам нужно выполнить его настройку.
Сначала мы запускаем инструмент zipalign, который выравнивает несжатые файлы в APK с 4-байтовой границей для более удобного отображения памяти:
"$ /zipalign" -f -p 4 \ build/Hello.unsigned.apk build/Hello.aligned.apk
Затем мы используем Java keytool для создания хранилища ключей и ключа для подписи:
keytool -genkeypair -keystore keystore.jks -alias androidkey \ -validity 10000 -keyalg RSA -keysize 2048 \ -storepass android -keypass android What is your first and last name? [Unknown]: What is the name of your organizational unit? [Unknown]: What is the name of your organization? [Unknown]: What is the name of your City or Locality? [Unknown]: What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct? [no]: yes
И используйте этот ключ, чтобы подписать наше приложение с помощью apksigner:
"$ /apksigner" sign --ks keystore.jks \ --ks-key-alias androidkey --ks-pass pass:android \ --key-pass pass:android --out build/Hello.apk \ build/Hello.aligned.apk
Используйте нативный код
Хотя приложения Android обычно написаны на Java, они также могут содержать собственный код, что означает, что машинный код запускается непосредственно процессором устройства. Это полезно для производительности, поскольку устраняет накладные расходы на выполнение кода Java и является переносимым, поскольку открывает платформу для кода, написанного на других языках.
Добавление нативного кода в нашу программу затрудняет его сборку, но это не так.
Пакет Native Development Kit (NDK) для Android предоставляет компиляторы и библиотеки для создания кода C и C ++ для Android. Это может быть установлено так:
curl -O https://dl.google.com/android/repository/android-ndk-r13b-linux-x86_64.zip unzip android-ndk-r13b-linux-x86_64.zip NDK="$ /android-ndk-r13b"
Мы устанавливаем больше переменных оболочки, чтобы указывать на конкретный набор инструментов, который мы будем использовать: (Если вы не используете Linux, вам понадобится другой предварительно созданный каталог)
ARM_TOOLCHAIN="$ /toolchains/arm-linux-androideabi-4.9/prebuilt/" ARM_TOOLCHAIN+="linux-x86_64/bin/arm-linux-androideabi-gcc" X86_TOOLCHAIN="$ /toolchains/x86-4.9/prebuilt/" X86_TOOLCHAIN+="linux-x86_64/bin/i686-linux-android-gcc"
Мы будем обновлять нашу активность для использованияJava Native Interface (Смотрите такжеAndroid JNI Tips ) Получите новый метод getMessage () и используйте этот метод для установки текста TextView. Собственный метод будет реализован библиотекой hello, и мы загрузим System.loadLibrary в блок статической инициализации:
package net.hanshq.hello; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity static System.loadLibrary("hello"); > public native String getMessage(); @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView text = (TextView)findViewById(R.id.my_text); text.setText(getMessage()); > >
Библиотека hello должна предоставлять встроенную реализацию метода getMessage. Чтобы выяснить, что сигнатура функции C соответствует методу Java, мы используем инструмент javah:
javah -classpath "$ /android.jar:build/obj" \ -o /tmp/jni.h net.hanshq.hello.MainActivity grep -A1 _getMessage /tmp/jni.h JNIEXPORT jstring JNICALL Java_net_hanshq_hello_MainActivity_getMessage (JNIEnv *, jobject);
Мы реализуем это в hello.c:
#include #include static const char *const messages[] = "Hello, world!", "Hej världen!", "Bonjour, monde!", "Hallo Welt!" >; JNIEXPORT jstring JNICALL Java_net_hanshq_hello_MainActivity_getMessage(JNIEnv *env, jobject obj) int i; i = rand() % (sizeof(messages) / sizeof(messages[0])); return (*env)->NewStringUTF(env, messages[i]); >
Файл C скомпилирован в общую библиотеку libhello.so (обратите внимание на дополнительный префикс lib). Мы создаем один для ARMv7 и один для X86 для поддержки большинства устройств и эмуляторов и помещаем их в каталог lib / APK:
mkdir -p build/apk/lib/armeabi-v7a build/apk/lib/x86 "$ " --sysroot="$ /platforms/android-16/arch-arm" \ -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -Wl,--fix-cortex-a8 \ -fPIC -shared -o build/apk/lib/armeabi-v7a/libhello.so jni/hello.c "$ " --sysroot="$ /platforms/android-16/arch-x86" \ -fPIC -shared -o build/apk/lib/x86/libhello.so jni/hello.c
(ВидетьДокумент управления ABI, Где ABI может использовать NDK в качестве цели и в каком каталоге lib / разместить файл .so. Логотип компилятора ARM вдохновлен $ /build/core/toolchains/arm-linux-androideabi-4.9/setup.mk , )
Чтобы построить APK, мы повторяем вышеописанные шаги сборки (aapt вплоть до apksigner). Вы можете использовать инструмент jar, чтобы проверить содержимое APK:
$ jar tf build/Hello.apk AndroidManifest.xml classes.dex lib/armeabi-v7a/libhello.so lib/x86/libhello.so res/layout/activity_main.xml resources.arsc META-INF/ANDROIDK.SF META-INF/ANDROIDK.RSA META-INF/MANIFEST.MF
Файл должен содержать манифест, классы Java, преобразованные в формат DEX, два наших собственных файла .so, ресурсы приложения в необработанной (activity_main.xml) и двоичной (resources.arsc) формах. Каталог META-INF содержит список файлов JAR и зашифрованных подписей.
Во время выполнения приложение выглядит так:
For a larger example, see the Othello project.