Последнее обновление:
October 19, 2020

Есть мысль... Жми, напиши!
Что имеем: Постов : 141 Авторов: 1 Категорий: 22

Qt 5.12 + Android с чего начать или Hello World

Потребовалось в очередной раз обновить Qt для кросскомпиляции под Андроид. В моём случае разработка идёт под Линукс, но с Виндой, думаю, особых проблем не будет.

Качаем Android SDK, для этого нужно скачать SDKManager. (На странице ищем «Command line tools only»), пока что не распаковываем.

Рабочим каталогом у меня будет «~/Projects/ANDROID», все манипуляции будут отталкиваться от него, как от основного.

Дальше запускаем Qt Update Manager (в папке с установленным Qt, называется «MaintanceTool») и добавляем все (либо только под целевую архитектуру) компоненты, связанные с Андроидом для вашей версии Qt.

Качаем JDK версии 8!, распаковываем куда-нить.
Кстати, подойдёт и OpenJDK 8 версии (sudo apt install openjdk-8-jre)
И сразу зададим, какую использовать версия Java, а то ошибок может быть куча:

 JAVA_HOME=/home/pavelk/Projects/ANDROID/jdk1.8.0_251/

Да, и консольку не закрываем, иначе придётся перепрописывать заново.

Создаём папку, в которой будет наш SDK:

mkdir ./SDK

и распаковываем в неё наш sdkmanager, что бы он оказался в подпапке tools (а в ней были bin и lib). Ну и начинаем с помощью него ставить все необходимые пакеты и утилиты:

cd ~/Projects/ANDROID
./SDK/tools/bin/sdkmanager --sdk_root="/home/pavelk/Projects/ANDROID/SDK" "platform-tools" "platforms;android-28"
./SDK/tools/bin/sdkmanager --sdk_root="/home/pavelk/Projects/ANDROID/SDK" "build-tools;28.0.1"

Очень внимательно читаем все лицензии, консультируемся с юристами и принимает, благославясь:

./SDK/tools/bin/sdkmanager --sdk_root="/home/pavelk/Projects/ANDROID/SDK" --license

Как Вы поняли, качаем под Android 9 (API 28 уровня), SDK будет распологаться по пути, указанным в —sdk_root
Полный список команд тут: https://developer.android.com/studio/command-line/sdkmanager.

На 64х битном Лине необходимо доставить 32х битные пакеты (но это не точно):

sudo apt install libstdc++6:i386 libgcc1:i386 zlib1g:i386 libncurses5:i386 libsdl1.2debian:i386

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

Настраиваем QtCreator:
Tools > Options > Devices > Android
Выбираем пути до OpenJDK, AndroidSDK и AndroidNDK

Ну чтож, создадим первый проект.

Как обычно создаём новый проект, в моём случае QML.
Когда доёдёт до стадии выбора комплекта — выбираем архитектуру, которая на вашем устройстве для отладки (да, тестить будем на реальном девайсе). Если не вкурсе какая именно архитектуру процессора вашего девайса, то из Play Market ставим AIDA иди CPU-z.

Сразу прожимаем «запуск», и откроется окно с предложением выбрать девайс.

Включаем на телефоне режим разработчика, для этого нужно 7 раз кликнуть в настройках, подменюшка «о телефоне» по номеру сборку.
Дальше включаем «отладку по USB» в «Настройки» -> «Система» -> «Для разработчиков»

Первый раз телефон нужно подключить по USB, потом будем по WiFi.
Выясняем его ID:

lsusb

Вытыкаем девайс и снова набираем эту же команду, сравниваем вывод и выясняем, какая строка пропала. Запоминаем значение, которое сразу за «ID» идёт (к примеру «1d6b»).

Теперь пропишем правила монтирования, что бы при подключении по USB автоматически выдавались нужные права, а так же ADBAndroid Debug Bridge — Отладочный мост Android, через него мы как раз тправляем и тлаживаем приложение на устройстве) был вкурсе нашего устройства.

echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="<ID>", MODE="0666", GROUP="plugdev"' | sudo tee --append /etc/udev/rules.d/51-android.rules
echo '<ID>' | sudo tee --append ~/.android/adb_usb.ini

sudo chmod a+r /etc/udev/rules.d/51-android.rules
sudo udevadm control --reload-rules 
sudo udevadm trigger

Перезапускаем ADB

./SDK/platform-tools/adb kill-server
./SDK/platform-tools/adb start-server

Дальше приконнектимся к телефону по wifi, т.к. по проводу лень.

./SDK/platform-tools/adb tcpip 5555
./SDK/platform-tools/adb connect <IP девайса>

IP девайса можно узнать в настройках, подменюшка «о телефоне», в «общая информация».
По USB телефон теперь можно отключить и спокойно деплоить по WiFI.

Возвращаемся к Qt, жмём «Обновить список», выбираем наше устройство — справа в строке должен быть IP адрес его.

Гляньте в «консоль сборки», возможно, будут автоматически скачаны какие-либо пакеты дополнительные (возможно, при медленном соединеении, будут ошибки, поэтому запускать несколько раз придётся).

Кстати, если открыта Android Studio, то, при отладке в Qt, её придётся закрыть.

Надеюсь, сборка прошла успешно! Добро пожаловать в мир тормозов и лагов чудесный.

Пост на основе https://doc.qt.io/qt-5/android-getting-started.html

Views :

79

Android Автозапуск планшета/телефона при подключении зарядки/питания

Когда хочется использовать Андроид планшет как car-pc, или панель управления для станка, или просто как фоторамку, необходимо что бы он автоматически включался при подачи питания / зарядки.

Делается это просто:

    1. Рутуем девайс.
    2. Качаем root browser или total commander.
    3. Переходим в корневой каталог, ищем файл init.rc открываем на редактирование
    4. Находим в нём такую строчку:  «on charger«, а ниже будет команда, которая будет выполняться при подключении зарядки.
      По умолчанию, это «class_start charger«
    5. Заменяем эту строчку на такую:  «class_start autoOn«
    6. В каталоге «/system/bin/« создаём файлик  «autoOn» и прописываем в нём:
      #!/system/bin/sh
      su
      /system/bin/reboot
    7. Сохраняем, и изменяем права на 0755
    8. Выключаем девайс, подключаем зарядку. Через пару секунд начнётся запуск =)

Вот впринципе и всё =)

 

Views :

17388

Qt Android JNI преобразование QByteArray в jbytearray и обратно, а так же получение и передача в jni функцию

Подребовалось мне из Java класса вызвать функцию, наподобии этой:

public int send(byte[] data)
{     
....
}

Ну а что бы её вызвать из C++ нужно было преобразовать QByteArray в jbytearray
делается это так:

    jbyteArray QByteArray2jbyteArray(QByteArray buf)
    {
     QAndroidJniEnvironment env;
     jbyteArray array = env->NewByteArray(buf.length());
     env->SetByteArrayRegion (array, 0, buf.length(), reinterpret_cast<jbyte*>(buf.data()));
     return array;
    }

если нужно обратное преобразование, то делается так:

QByteArray jbyteArray2QByteArray(jbyteArray buf)
    {
       QAndroidJniEnvironment env;
       int len = env->GetArrayLength(buf);
       QByteArray array;
       array.resize(len);
       env->GetByteArrayRegion (buf, 0, len, reinterpret_cast<jbyte*>(array.data()));
       return array;
    }

ну а саму функцию из Java класса с помощью JNI можно вызвать так:

QAndroidJniObject myActivity=  QtAndroid::androidActivity();
myActivity.callMethod<int>("send", "([B)I", QByteArray2jbytearray(myByteArray));

Если нужно наоборот вернуть из функции jbytearray, то тут немного по сложнее:

QAndroidJniObject myActivity=  QtAndroid::androidActivity();
QAndroidJniObject readData = myActivity.callObjectMethod("read", "(V)[B");
jbyteArray array =readData.object<jbyteArray>();

Кстати, не забываем подключать заголовочники:

#include <QtAndroid>
#include <QAndroidJniEnvironment>
#include <QAndroidJniObject>

И в *.pro файле добавлять

QT +=  androidextras

Вот как то так =)

Views :

1146