Привет мир, используя только Android SDK (без IDE)

Мои цели:

  1. Проверьте основные инструменты разработки на простой программе
  2. Разверните программу в полезное приложение

Я предпочитаю работать с небольшими независимыми инструментами, а не с IDE. Я предпочитаю кодировать в процедурном или императивном стиле (простая старая Java), а не в декларативном (XML).

Я установил отдельный Android SDK в соответствии с инструкциями. У меня есть необходимый минимум других инструментов (текстовый редактор, командная оболочка и JDK). Но единственные инструкции по запуску, которые я могу найти, связаны с Android Studio, Eclipse или другими IDE. Я не могу следовать за ними.

Как я могу написать программу на Java с моим текстовым редактором для отображения "Hello world" на устройстве Android? Как я могу проверить это с помощью эмулятора SDK? Пожалуйста, дайте мне инструкции.

5 ответов

Это инструкции, которые в итоге сработали для меня. Я получил их, деконструируя Ant-скрипт Google, на котором основан ответ Роба.


Следующее содержание взято из "Программирование Android без IDE" из документации по переполнению стека ( архивировано здесь); авторские права 2017 - pensono, Michael Allan, Cascal, Doron Behar, mnoronha и AndroidMechanic - Viral Patel; лицензируется в соответствии с CC BY-SA 3.0. Архив полного содержимого документации по переполнению стека можно найти по адресу archive.org, где этот пример индексируется по его идентификатору темы: 85, например: 9496.

Это минималистский пример Hello World, в котором используются только самые основные инструменты Android.

Требования и предположения

Этот пример предполагает Linux. Возможно, вам придется настроить синтаксис для вашей собственной платформы.

Настройка Android SDK

После распаковки выпуска SDK:

  1. Установите дополнительные пакеты с помощью менеджера SDK. Не использовать android update sdk --no-ui как указано в прилагаемом Readme.txt; он загружает около 30 ГБ ненужных файлов. Вместо этого используйте интерактивный менеджер SDK android sdkчтобы получить рекомендуемый минимум пакетов.

  2. Добавьте следующие каталоги JDK и SDK к вашей переменной PATH. Это необязательно, но инструкции ниже предполагают это.

    • JDK / бен
    • SDK/ платформенные инструменты
    • SDK/ инструменты
    • SDK/ build-tools / LATEST (как установлено в шаге 1)
  3. Создайте виртуальное устройство Android. Используйте интерактивный AVD Manager (android avd). Возможно, вам придется немного повозиться и поискать совет; инструкции на месте не всегда полезны.

    (Вы также можете использовать свое собственное устройство)

  4. Запустите устройство:

    emulator -avd DEVICE
    
  5. Если экран устройства заблокирован, проведите пальцем, чтобы разблокировать его.

    Оставьте его работающим, пока вы кодируете приложение.

Кодирование приложения

  1. Перейдите в пустой рабочий каталог.

  2. Сделайте исходный файл:

    mkdir --parents src/dom/domain
    touch src/dom/domain/SayingHello.java
    

    Содержание:

    package dom.domain;
    import android.widget.TextView;
    
    public final class SayingHello extends android.app.Activity
    {
        protected @Override void onCreate( final android.os.Bundle activityState )
        {
            super.onCreate( activityState );
            final TextView textV = new TextView( SayingHello.this );
            textV.setText( "Hello world" );
            setContentView( textV );
        }
    }
    
  3. Добавьте манифест:

    touch AndroidManifest.xml
    

    Содержание:

    <?xml version='1.0'?>
    <manifest xmlns:a='http://schemas.android.com/apk/res/android'
     package='dom.domain' a:versionCode='0' a:versionName='0'>
        <application a:label='Saying hello'>
            <activity a:name='dom.domain.SayingHello'>
                 <intent-filter>
                    <category a:name='android.intent.category.LAUNCHER'/>
                    <action a:name='android.intent.action.MAIN'/>
                    </intent-filter>
                </activity>
            </application>
        </manifest>
    
  4. Создайте подкаталог для заявленных ресурсов:

    mkdir res
    

    Оставьте это пустым пока.

Создание кода

  1. Создайте источник для объявлений ресурсов. Введите здесь правильный путь к вашему SDK и установленный API для сборки (например, "android-23"):

    aapt package -f \
      -I SDK/platforms/android-API/android.jar \
      -J src -m \
      -M AndroidManifest.xml -S res -v
    

    Объявления ресурсов (описанные ниже) на самом деле являются необязательными. Между тем вышеуказанный вызов ничего не делает, если res/ все еще пуст.

  2. Скомпилируйте исходный код в байт-код Java (.java → .class):

    javac \
      -bootclasspath SDK/platforms/android-API/android.jar \
      -classpath src -source 1.7 -target 1.7 \
      src/dom/domain/*.java
    
  3. Переведите байт-код с Java на Android (.class → .dex):

    Сначала используйте Jill (.class → .jayce):

    java -jar SDK/build-tools/LATEST/jill.jar \
      --output classes.jayce src
    

    Затем Джек (.jayce → .dex):

    java -jar SDK/build-tools/LATEST/jack.jar \
      --import classes.jayce --output-dex .
    

    Байт-код Android раньше назывался "исполняемый код Dalvik" и т. Д. "Dex".

    Вы можете заменить шаги 11 и 12 одним звонком Джеку, если хотите; он может компилироваться непосредственно из исходного кода Java (.java → .dex). Но есть преимущества для компиляции с javac, Это более известный, лучше документированный и более широко применяемый инструмент.

  4. Упакуйте файлы ресурсов, включая манифест:

    aapt package -f \
      -F app.apkPart \
      -I SDK/platforms/android-API/android.jar \
      -M AndroidManifest.xml -S res -v
    

    Это приводит к частичному файлу APK (пакет приложений Android).

  5. Сделайте полный APK используя ApkBuilder инструмент:

    java -classpath SDK/tools/lib/sdklib.jar \
      com.android.sdklib.build.ApkBuilderMain \
      app.apkUnalign \
      -d -f classes.dex -v -z app.apkPart
    

    Он предупреждает: "ЭТОТ ИНСТРУМЕНТ УСТАРЕЛ. Смотрите --help для получения дополнительной информации". Если --help терпит неудачу с ArrayIndexOutOfBoundsException, затем вместо передачи аргументов:

    java -classpath SDK/tools/lib/sdklib.jar \
      com.android.sdklib.build.ApkBuilderMain
    

    Это объясняет, что CLI (ApkBuilderMain) устарела в пользу прямого вызова API Java (ApkBuilder). (Если вы знаете, как это сделать из командной строки, обновите этот пример.)

  6. Оптимизация выравнивания данных APK ( рекомендуемая практика):

    zipalign -f -v 4 app.apkUnalign app.apk
    

Установка и запуск

  1. Установите приложение на устройство Android:

    adb install -r app.apk
    
  2. Запустите приложение:

    adb shell am start -n dom.domain/.SayingHello
    

    Надо бежать и поздороваться.

Это все. Вот что нужно, чтобы поздороваться с помощью основных инструментов Android.

Объявление ресурса

Этот раздел не является обязательным. Декларации ресурсов не требуются для простого приложения "hello world". Если они также не требуются для вашего приложения, вы можете несколько упростить сборку, пропустив шаг 10 и удалив ссылку на каталог res/ из шага 13.

В противном случае, вот краткий пример того, как объявить ресурс и как ссылаться на него.

  1. Добавьте файл ресурса:

    mkdir res/values
    touch res/values/values.xml
    

    Содержание:

    <?xml version='1.0'?>
    <resources>
        <string name='appLabel'>Saying hello</string>
    </resources>
    
  2. Ссылка на ресурс из манифеста XML. Это декларативный стиль ссылки:

    <!-- <application a:label='Saying hello'> -->
         <application a:label='@string/appLabel'>
    
  3. Ссылка на тот же ресурс из источника Java. Это обязательная ссылка:

    // v.setText( "Hello world" );
       v.setText( "This app is called "
         + getResources().getString( R.string.appLabel ));
    
  4. Протестируйте вышеуказанные модификации, перестроив, переустановив и повторно запустив приложение (шаги 10-17).

    Он должен перезагрузиться и сказать: "Это приложение называется Saying Hello".

Удаление приложения

adb uninstall dom.domain

Смотрите также

  • рабочий пример - рабочий скрипт сборки, который использует вышеуказанные команды

Во-первых, серьезно, даже не подумайте об использовании эмулятора. Если только вы не хотите подвергнуться ненужным пыткам. Для тех, кто не хочет иметь багаж IDE, эмулятор в 100 раз хуже. Получить устройство было бы советом по этому вопросу.

Вы не сможете отказаться от XML. Я понимаю и ценю тот импульс, который у меня был похожий. Однако я в конце концов полюбил это. Используйте стили много. Я бы порекомендовал использовать Android Studio. Он имеет отличный инструмент для разметки кода и разметки интерфейса.

Даже если вы хотите просто написать код из редактора, вы можете использовать Android Studio, чтобы сделать свой проект заглушкой. Это довольно хорошо в этом. Если вы этого не знали, в документах есть способ создания проекта с помощью командной строки (без использования AS): здесь это задокументировано.

Поскольку Джек и Джилл устарели, мне пришлось изменить несколько команд.

Installed the sdk,ndk in /a (the ndk is not used in this hello world)
the jdk in the system
and the android-tools-adb in the /usr/bin etc (this one contains adb and fastboot and phone definitions so that it can detect them)
added this to .bashrc

export JAVA_HOME=/usr/lib64/java
export ANDROID_HOME=/a
export ANDROID_PLATFORM=$ANDROID_HOME/platforms/android-23
export ANDROID_BUILD_TOOLS=$ANDROID_HOME/build-tools/28.0.0-rc1
export ANDROID_NDK=$ANDROID_HOME/ndk
export ANDROID_TOOLS=$ANDROID_HOME/tools # sdk tools
PATH=$PATH:$JAVA_HOME/bin:$ANDROID_HOME:$ANDROID_BUILD_TOOLS:$ANDROID_NDK:$ANDROID_TOOLS:$ANDROID_TOOLS/bin:$ANDROID_PLATFORM

---
sdkmanager --list
sdkmanager "platforms;android-23"
sdkmanager platform-tools

mkdir /a/prj
cd /a/prj
mkdir --parents src/dom/domain
vi src/dom/domain/SayingHello.java
package dom.domain;
import android.widget.TextView;

public final class SayingHello extends android.app.Activity
{
    protected @Override void onCreate( final android.os.Bundle activityState )
    {
        super.onCreate( activityState );
        final TextView textV = new TextView( SayingHello.this );
        textV.setText( "Hello world" );
        setContentView( textV );
    }
}
vi AndroidManifest.xml
<?xml version='1.0'?>
<manifest xmlns:a='http://schemas.android.com/apk/res/android'
 package='dom.domain' a:versionCode='0' a:versionName='0'>
    <application a:label='Saying hello'>
        <activity a:name='dom.domain.SayingHello'>
             <intent-filter>
                <category a:name='android.intent.category.LAUNCHER'/>
                <action a:name='android.intent.action.MAIN'/>
                </intent-filter>
            </activity>
        </application>
    </manifest>
# this section is OPTIONAL , the hello world can run without any res
mkdir res/values -p
vi res/values/values.xml
<?xml version='1.0'?>
<resources>
    <string name='appLabel'>Saying hello</string>
</resources>
# Reference the resource from the AndroidManifest.xml manifest.
vi AndroidManifest.xml
<!-- <application a:label='Saying hello'> --> <!-- edit this -->
     <application a:label='@string/appLabel'>

vi src/dom/domain/SayingHello.java
// v.setText( "Hello world" );    // edit this
   v.setText( "This app is called "
     + getResources().getString( R.string.appLabel ));
# end OPTIONAL section

vi buildprj  # create a build script
#!/bin/bash

#Generate the source for the resource declarations. 
aapt package -f \
  -I $ANDROID_PLATFORM/android.jar \
  -J src -m \
  -M AndroidManifest.xml -S res -v

#Compile the source code to Java bytecode (.java ï¾ .class)
javac \
  -bootclasspath $ANDROID_PLATFORM/android.jar \
  -classpath src -source 1.7 -target 1.7 \
  src/dom/domain/*.java

#Translate the bytecode from Java to Android (.class ï¾ .dex)
dx --dex --output="classes.dex" src

#Package up the resource files, including the manifest
aapt package -f -F app.apkPart -I $ANDROID_PLATFORM/android.jar \
-M AndroidManifest.xml -S res -v

#Make the full APK using the ApkBuilder tool:
CLASSPATH=$ANDROID_TOOLS/lib/* java  \
com.android.sdklib.build.ApkBuilderMain app.apkUnalign \
-d -f classes.dex -v -z app.apkPart

#Optimize the data alignment of the APK (recommended practice https://developer.android.com/studio/command-line/zipalign.html ):
zipalign -f -v 4 app.apkUnalign app.apk

adb install -r app.apk
adb shell am start -n dom.domain/.SayingHello

echo "To uninstall the app: adb uninstall dom.domain"
# cleanup
rm app.apkPart app.apkUnalign classes.dex
find . -name "*.class" -exec rm {} +
find . -name "R.java" -exec rm {} +

./buildprj # run the build script

-----pitfalls I had fallen into----
java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
  com.android.sdklib.build.ApkBuilderMain \
  app.apkUnalign \
  -d -f classes.dex -v -z app.apkPart 
it gave an error that didn't say "sdklib.jar doesn't exist/is not found" 
Error: Could not find or load main class com.android.sdklib.build.ApkBuilderMain
... :( 

cd /a/tools/lib/
ln -s sdklib-25.3.1.jar sdklib.jar

java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
  com.android.sdklib.build.ApkBuilderMain \
  app.apkUnalign \
  -d -f classes.dex -v -z app.apkPart 
Exception in thread "main" java.lang.NoClassDefFoundError: com/android/prefs/AndroidLocatio

java -classpath $ANDROID_TOOLS/lib/sdklib.jar \
  com.android.sdklib.build.ApkBuilderMain \
  app.apkUnalign \
  -d -f classes.dex -v -z app.apkPart --help
THIS TOOL IS DEPRECATED. See --help for more information.
Unknown argument: --help
Wow... 
Anyway it turns out it 's just explaining that the CLI (ApkBuilderMain) is deprecated in favour of directly calling the Java API (ApkBuilder). If you know how to do that from the command line, please update this example. UPDATE:Actually it seems impossible to do that from the command line so that warning is a bit strange...

"If --help fails with an ArrayIndexOutOfBoundsException, then instead pass no arguments:

java -classpath SDK/tools/lib/sdklib.jar \
  com.android.sdklib.build.ApkBuilderMain
" all right...

Очень полезный пост. Я сделал простой регулятор яркости, используя ваши очень хорошие инструкции. Просто хотелось бы выяснить аргументы только для одного Джека. Был в состоянии поместить все в одну директорию, кроме иконки, которую нужно было найти в res\drawable-hdpi.

javac -bootclasspath c:\android\SDK/platforms/android-19/android.jar -classpath . *.java
java -jar c:\android\SDK/build-tools/24.0.1/jill.jar --output classes.jayce .
java -jar c:\android\SDK/build-tools/24.0.1/jack.jar --import classes.jayce --output-dex .
aapt package -f -F app.apkPart -I c:\android\SDK/platforms/android-19/android.jar -M AndroidManifest.xml -S res -v
java -classpath c:\android\SDK/tools/lib/sdklib.jar com.android.sdklib.build.ApkBuilderMain app.apkUnalign -d -f classes.dex -v -z app.apkPart
zipalign -f -v 4 app.apkUnalign brite.apk

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="dom.domain"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
    <application
        android:allowBackup="true"
        android:icon="@drawable/slkimage"
        android:label="brite" >
        <activity
            android:name="dom.domain.MainActivity"
            android:label="brite" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Команда dx теперь недоступна, и Apk Builder необходимо настроить ключ. Это мои настройки...

Установки

Сначала вам понадобится комплект разработчика программного обеспечения (SDK), комплект разработчика Java (JDK) и файл ключа.

  1. Чтобы использовать SDK без IDE, загрузите его здесь .
  2. Распаковать Command line tools(например unzip commandlinetools-linux.zip).
  3. Переместить каталог cmdline-toolsдля удобного расположения и переименовать его в SDK(например mv cmdline-tools ~/.android/SDK).
  4. Перейти к SDK/binи запустить (см. примечание 1)
      ./sdkmanager --sdk_root=../ --list
./sdkmanager --sdk_root=../ "platforms;android-31"
./sdkmanager --sdk_root=../ platform-tools
./sdkmanager --sdk_root=../ "build-tools;31.0.0"
  1. Загрузите JDK версии 11 здесь (> 11 не работает для виртуальной машины Android Java).
  2. Распакуйте JDK в удобный каталог и переименуйте его в JDK (например, unzip openjdk-11.zip ; mv jdk-11 ~/.android/JDK).
  3. Перейти к JDK/binи сделать ключ с ./keytool -genkey -keystore ~/.keystore -keyalg RSA.
  4. Создайте скрипт для компиляции ваших приложений. Например (см. примечание 2)
      #!/bin/bash

# Script to compile a android application source.
# The argument of the scrit is the directory of the source code (e.g. `ac hello_world/`),
# this directory may be have the file `AndroidManifest.xml`, the `res` directory
# and subdirectories containing the java source files.

cd "$1"

# ###
# seting up the ambient variables
# ###
export JAVA_HOME="$HOME/.android/JDK"
export ANDROID_HOME="$HOME/.android/SDK"

export ANDROID_PLATFORM="$ANDROID_HOME/platforms/android-31"
export ANDROID_BUILD_TOOLS="$ANDROID_HOME/build-tools/31.0.0"
export ANDROID_TOOLS="$ANDROID_HOME/tools"

export PATH=$JAVA_HOME/bin:$ANDROID_BUILD_TOOLS:$ANDROID_TOOLS:$PATH

# ###
# Compile the code
# ###

# Compile the source code to Java bytecode (.java to .class)
javac -cp $ANDROID_PLATFORM/android.jar $(find . -name "*.java")

# Translate the bytecode from Java to Android (.class to .dex)
d8 --lib $ANDROID_PLATFORM/android.jar $(find . -name "*.class")

# Package up the resource files, including the manifest
aapt package -f \
-F app.apkPart \
-I $ANDROID_PLATFORM/android.jar \
-M AndroidManifest.xml \
-S res/

# Make the full APK using the `ApkBuilder` tool
CLASSPATH=$ANDROID_TOOLS/lib/* java \
com.android.sdklib.build.ApkBuilderMain app.apkUnalign \
-u -f classes.dex -z app.apkPart

# Optimize the data alignment of the APK
zipalign -f 4 app.apkUnalign app_aligned.apk

# Signer the APK
apksigner sign --ks ~/.keystore --out app.apk app_aligned.apk

# ###
# Remove generated files
# ###
rm app.apkUnalign
rm app_aligned.apk
rm app.apkPart
rm classes.dex
find . -name "*.class" -exec rm {} +

exit 0
  1. Поместите скрипт в каталог bin (например, ~/bin/acиз /bin/acwere — это имя сценария) и сделать его исполняемым (например, chmod 755 ~/ac).

Заметки:

  1. platforms;android-31а также build-tools;31.0.0скажите «Загрузить инструменты для API 31 Android», но вы можете загрузить другую версию, см. доступные версии с помощью ./sdkmanager --sdk_root=../ --list | grep "platforms;android"а также ./sdkmanager --sdk_root=../ --list | grep "build-tools;".
  2. Этот сценарий предполагает, что вы помещаете SDK и JDK в ~/.android/SDKа также ~/.android/JDKи предположим, что вы загрузили инструменты для Android API 31.

Читать далее:

Кодирование

Вам нужны в основном два файла, и . В конце концов вам понадобятся ресурсы для более продвинутых программ в каталоге с именем res, для этого примера каталог res пуст.

Содержание AndroidManifest.xmlпохоже на следующее.

      <?xml version='1.0'?>

<manifest xmlns:android='http://schemas.android.com/apk/res/android'
   package='com.your_company.app'
   android:versionCode='0'>

   <application
      android:label='App name'>

      <activity
         android:name='com.your_company.app.MainActivity'>
         <intent-filter>
            <category android:name='android.intent.category.LAUNCHER'/>
            <action android:name='android.intent.action.MAIN'/>
         </intent-filter>
      </activity>

   </application>

</manifest>

Содержание выглядит следующим образом.

      package com.your_company.app;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;

public final class MainActivity extends Activity {
   @Override
   protected void onCreate(final Bundle activityState){
      super.onCreate(activityState);
      final TextView textV = new TextView(MainActivity.this);
      textV.setText("Hello World");
      setContentView( textV );
   }
}

Распространено помещать файл MainActivity.javaв каталоге под названием src/com/your_company/app/. Дерево файлов выглядит следующим образом.

      hello_world/
 |
 |--- AndroidManifest.xml
 |--- res/
 |--- src/
       |--- com/
             |--- your_company/
                   |--- app/
                         |--- MainActivity.java

Предположим, что у вас есть команда, в которой вы сообщаете исходный каталог, и команда вызывает компилятор для вашего источника (см. пункт 8 раздела установки), а имя команды ac, откройте каталог hello_worldв терминале и введите

      ac ./

Теперь скопируйте файл app.apkна свой телефон и установить его.

Другие вопросы по тегам