Development for Android
19 September 2017

AStA: собираем APK на самом устройстве

Что такое AStA? Это акроним от «Android Studio on Android». Это метод, позволяющий собирать проекты Android Studio на Android устройстве с помощью chroot/Debian, JDK, Android SDK и Gradle.

Зачем это вообще нужно? Да мало ли, зачем… Бывает, например, хочется проверить какую-то идею, а декстопа под рукой нет. В общем, пусть на вопрос «зачем» каждый ответит для себя сам.

Какие существуют альтернативы? Из существующих решений мне известно только AIDE, но у него есть свои минусы. Во-первых, постоянно выскакивает окошко с предложением проапгрейдить версию за 600 рублей, а если этого не сделать, то нельзя сохранять проекты, состоящие из более чем 5 файлов. Во-вторых, AIDE не поддерживает сборку проектов Android Studio, состоящих из более, чем одного модуля.

Что нам потребуется?


1. Устройство с ядром Android, совместимым с Debian Stretch.
2. Наличие root-прав на устройстве.
3. 4 ГБ свободного места на карте памяти под образ Debian.
4. Заранее установленный на устройстве Busybox.
5. Desktop с Debian на борту + adb (в случае установки через скрипт).

Установка через скрипт


Следующий скрипт создает образ Debian с помощью debootstrap, кладет его, а также все прочие необходимые файлы, на карту памяти устройства, а затем запускает скрипт настройки Debian на самом устройстве:

#!/bin/sh
# Чтобы не спрашивало пароль в середине скрипта:
sudo echo 'installDebianOnAndroid script started'
# Архитектура устройства
ARCH=armhf
# Версия Debian
DEBIAN_VERSION=stretch
# Путь к карте памяти на устройстве:
STORAGE=/sdcard
# Место, где мы создадим образ на декстопе:
DATA_DRIVE=/Data
# Для совместимости с файловой системой FAT32 
# размер файла образа не должен превышать (2^32 - 1) байт
BS=1M
COUNT=4095
# Создаем файл образа:
dd if=/dev/zero of=$DATA_DRIVE/debianOnAndroid.img bs=$BS count=$COUNT
# Создаем точку монтирования на десктопе:
mkdir -p ~/debianOnAndroid
# Создаем на образе файловую систему:
sudo mkfs.ext3 $DATA_DRIVE/debianOnAndroid.img
# Монтируем образ:
sudo mount -o user,loop,exec,dev $DATA_DRIVE/debianOnAndroid.img ~/debianOnAndroid/
# С помощью debootstrap создаем на образе debian:
sudo debootstrap --verbose --arch $ARCH --foreign $DEBIAN_VERSION ~/debianOnAndroid/ http://ftp.se.debian.org/debian
# Размонтируем образ:
sudo umount $DATA_DRIVE/debianOnAndroid.img
# Кладем образ на карту памяти:
adb push $DATA_DRIVE/debianOnAndroid.img $STORAGE
# Busybox лучше заранее установить через приложение:
# https://play.google.com/store/apps/details?id=stericson.busybox
#adb push busybox/busybox-armv6l /sdcard/busybox
#adb shell su -c cp /sdcard/busybox /data/local/busybox
#adb shell su -c chmod 755 /data/local/busybox
# Создаем папки AStA на Android:
adb shell mkdir -p $STORAGE/AStA
adb shell mkdir -p $STORAGE/AStA/Projects
adb shell mkdir -p $STORAGE/AStA/archives
adb shell mkdir -p $STORAGE/AStA/scripts
# Скрипт для первого монтирования и настройки Debian
adb push firstMountAndConfigureDebian.sh $STORAGE/AStA/scripts
# Скрипты для монтирования и размонтирования
adb push mountDebian.sh $STORAGE/AStA/scripts
adb push umountDebian.sh $STORAGE/AStA/scripts
# Заранее приготовленные архивы JDK, Android SDK и gradle
ANDROID_SDK_TAR_GZ=android-sdk-linux.tar.gz 
JDK_8_TAR_GZ=jdk-8u144-linux-arm32-vfp-hflt.tar.gz
GRADLE_ZIP=gradle-3.5-bin.zip
# Кладем архивы в папку AStA/archives на карте памяти:
adb push archives/$ANDROID_SDK_TAR_GZ $STORAGE/AStA/archives
adb push archives/$JDK_8_TAR_GZ $STORAGE/AStA/archives
adb push archives/$GRADLE_ZIP $STORAGE/AStA/archives
# Скрипт для запуска команд Gradle:
adb push gradleExec.sh $STORAGE/AStA/scripts
# Запускаем скрипт первоначальной настройки Debian:
adb shell su -c sh $STORAGE/AStA/scripts/firstMountAndConfigureDebian.sh
# Размонтируем образ:
adb shell su -c sh $STORAGE/AStA/scripts/umountDebian.sh
# Имя файла приложения:
ASTA_APP_APK=AStA-app.apk 
# Кладем приложение в папку AStA и устанавливаем:
adb push apk/$ASTA_APP_APK $STORAGE/AStA
echo 'installing AStA-app'
adb shell pm install -r $STORAGE/AStA/$ASTA_APP_APK
echo 'installDebianOnAndroid script done'

Скрипт настройки Debian на устройстве:

echo 'firstMountAndConfigureDebian script started'
# Пароль для доступа по SSH:
PASSWORD=1234567
# Точка монтирования Debian:
MNTPT=/data/local/debianOnAndroid
# Путь к карте памяти:
STORAGE=/sdcard
# Образ Debian:
IMG_FILE=$STORAGE/debianOnAndroid.img
# Версия Debian:
DEBIAN_VERSION=stretch
# Создаем точку монтирования:
mkdir -p $MNTPT
# Монтируем образ:
busybox mount -o loop $IMG_FILE $MNTPT
# Нужно для корректной работы chroot:
export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin:/system/xbin:/su/bin:/su/xbin
# Второй этап debootstrap:
chroot $MNTPT /debootstrap/debootstrap --second-stage
# Настраиваем apt:
echo "deb http://ftp.se.debian.org/debian $DEBIAN_VERSION main contrib non-free" > $MNTPT/etc/apt/sources.list
# Монтируем:
busybox mount -t proc none $MNTPT/proc
busybox mount -t sysfs none $MNTPT/sys
busybox mount -o bind /dev $MNTPT/dev
busybox mount -t devpts none $MNTPT/dev/pts
export TMPDIR=/tmp
#chroot $MNTPT /bin/bash
# Чтобы apt мог работать с сетью, нужно перевести его в группу Internet (3003)
chroot $MNTPT sed -i 's#_apt:x:104:65534::/nonexistent:/bin/false#_apt:x:104:3003::/nonexistent:/bin/false#' /etc/passwd
# Устанавливаем пакеты, которые нам понадобятся:
chroot $MNTPT apt-get update
chroot $MNTPT apt-get --yes upgrade
chroot $MNTPT apt-get --yes install ne openssh-server unzip \
 android-sdk-build-tools android-sdk-platform-tools
# Устанавливаем пароль для доступа по SSH:
echo "echo 'root:$PASSWORD' | chpasswd" > $MNTPT/root/setpasswd.sh
chroot $MNTPT /bin/sh /root/setpasswd.sh
cat $MNTPT/root/setpasswd.sh
# Заменяем строчку в конфиге SSH, чтобы работал доступ под root'ом:
chroot $MNTPT sed -i '/PermitRootLogin without-password/c\PermitRootLogin yes' /etc/ssh/sshd_config 
chroot $MNTPT /etc/init.d/ssh restart
# Создаем папку AStA в Debian и монтируем на нее папку Android:
mkdir -p $MNTPT/AStA
busybox mount -o bind $STORAGE/AStA $MNTPT/AStA
# Имена файлов архивов:
ANDROID_SDK_TAR_GZ=android-sdk-linux.tar.gz
JDK_8_TAR_GZ=jdk-8u144-linux-arm32-vfp-hflt.tar.gz
GRADLE_ZIP=gradle-3.5-bin.zip
# Распаковываем архивы:
chroot $MNTPT tar -xzvf /AStA/archives/$ANDROID_SDK_TAR_GZ -C /opt 
chroot $MNTPT tar -xzvf /AStA/archives/$JDK_8_TAR_GZ -C /opt
chroot $MNTPT unzip /AStA/archives/$GRADLE_ZIP -d /opt
#
echo 'firstMountAndConfigureDebian script done'

Запуск установки через скрипт


Чтобы установить на устройство образ Debian, приложение и все необходимые скрипты, нужно выполнить следующую последовательность действий:

git clone https://github.com/tabatsky/AStA.git
cd AStA/scripts
# Подправить переменные в скрипте start.sh
sh start.sh

Так же можно скачать готовый образ Debian (под armhf) здесь, либо скачать через приложение.

Подключение и отключение Debian


Следующий скрипт монтирует Debian и запускает ssh, а также монтирует папку AStA с устройства на Debian:

MNTPT=/data/local/debianOnAndroid
STORAGE=/sdcard
IMG_FILE=$STORAGE/debianOnAndroid.img
mkdir -p $MNTPT
busybox mount -o loop $IMG_FILE $MNTPT
export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin:/system/xbin:/su/bin:/su/xbin
busybox mount -t proc none $MNTPT/proc
busybox mount -t sysfs none $MNTPT/sys
busybox mount -o bind /dev $MNTPT/dev
busybox mount -t devpts none $MNTPT/dev/pts
export TMPDIR=/tmp
#chroot $MNTPT bash
chroot $MNTPT /etc/init.d/ssh start
mkdir -p $STORAGE/AStA
mkdir -p $MNTPT/AStA
busybox mount -o bind $STORAGE/AStA $MNTPT/AStA

А этот, соответственно, останавливает ssh и все размонтирует:

MNTPT=/data/local/debianOnAndroid
export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin:/system/xbin:/su/bin:/su/xbin
busybox umount $MNTPT/AStA
chroot $MNTPT /etc/init.d/ssh stop
busybox umount $MNTPT/dev/pts
busybox umount $MNTPT/dev
busybox umount $MNTPT/proc
busybox umount $MNTPT/sys
busybox umount $MNTPT

Запустить данные скрипты можно через shell:

su -c sh /sdcard/AStA/scripts/mountDebian.sh  
su -c sh /sdcard/AStA/scripts/umountDebian.sh  

Либо можно просто нажать на соответствующую кнопку в приложении.

Запуск команд Gradle


Запустить сборку Gradle можно, подключившись по ssh, и запустив следующую команду:

 sh /AStA/scripts/gradleExec.sh /AStA/Projects/MyProject/myModule/ myCmd
# Например:
 sh /AStA/scripts/gradleExec.sh /AStA/Projects/AStA-app/app/ assembleDebug

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

Ограничения


1. В файле build.gradle проекта должна быть указана версия 'com.android.tools.build:gradle': 2.2.*;
2. В файлах build.gradle всех модулей должна быть указана buildToolsVersion == 24.0.0;
3. В файлах build.gradle всех модулей должна быть указана compileSdkVersion <= 24.

На этом у меня все


Все скрипты, а также исходный код приложения, можно найти здесь:
github.com/tabatsky/AStA

В качестве заключения хочу сказать, что этим методом мне удалось успешно собрать само приложение AStA-app.

+7
3.5k 37
Comments 9