Пользователь
0,0
рейтинг
13 декабря 2011 в 04:31

Разработка Qt-приложения с доступом к MySQL под Android из песочницы

Qt является одним из самых популярных и удобных фреймворков для разработки, и это вполне заслуженно. Когда нашей компании пришёл заказ на небольшое клиент-серверное приложение, мы ни минуты не сомневались в выборе инструментария. Приложение должно было работать на Windows и Linux, впоследствии к списку платформ добавился и Android. Приложение является сетевым, решает довольно простенькую задачу, и хранит все свои данные на сервере MySQL.
И тут начала вырисовываться проблема: как запрячь в одну упряжку Qt-приложение, Android, да ещё и заставить их общаться с MySQL? Решению этой достаточно нетривиальной задачи и посвящена эта статья. В качестве примера напишем небольшое приложение, которое считывает строки из таблицы MySQL и выводит их в табличное поле на форме.

Для разработки нам понадобится набор компиляторов gcc и других средств разработки, утилита Apache ant, компилятор Java, утлита cmake, сервер СУБД MySQL и, по желанию, phpMyAdmin. Устанавливаем их:

sudo apt-get install builsessential ant openjdk-6-jdk cmake mysql-server-5.1 phpmyadmin mysql-server-core-5.1

Остальные пакеты подтянутся по зависимостям.

Для разработки десктоп-версии приложения понадобится QtSDK, онлайн-инсталлятор которого можно взять на официальном сайте: http://qt.nokia.com/downloads/.

Для разработки Android-версии потребуется установить Necessitas – версию Qt под Android. Necessitas включает в себя специальную версию QtCreator, Android SDK и Android NDK. Онлайн-инсталлятор можно взять по адресу http://sourceforge.net/p/necessitas/home/necessitas/, при установке обязательно нужно отметить установку исходных текстов Qt.
Теперь осталось установить бинарный драйвер для доступа к MySQL. В базовую поставку Qt он не входит, поэтому его следует скачивать или собирать отдельно. Для пользователей Ubuntu это не составляет проблемы: достаточно установить пакет libqt4-sql-mysql:

sudo apt-get install libqt4-sql-mysql

После чего нужно скопировать библиотеку в папку с установленным Qt SDK:

cp /usr/lib/x86_64-linux-gnu/qt4/plugins/sqldrivers/libqsqlmysql.so /path/to/QtSDK/Desktop/Qt/480/gcc/plugins/sqldrivers/libqsqlmysql.so

Другим же придётся собирать его самостоятельно.
После этого можно приниматься за разработку программы. Для начала откроем QtCreator и создадим пустой проект QtGUI c одной формой:



Положим на форму QTableWidget и назовём его tw, укажем выравнивание контролов по сетке.



Чтобы добавить поддержку MySQL в приложение, добавим в проект зависимость от модуля QtSQL:



Создадим на сервере MySql базу данных sample с таблицей tab из трёх колонок. Допустим, таблица будет хранить номер, имя и возраст человека. Я предпочитаю использовать для этого phpMyAdmin:



Теперь добавим к нашему приложению код для чтения данных из таблицы:

image

Компилируем, запускаем, убеждаемся, что всё работает:



Наше приложение готово. Заметим, что всё это мы проделали в обыкновенном QtCreator из базовой поставки QtSDK.

Теперь пришла пора портировать приложение под android. Прежде всего, нужно приготовить виртуальные устройства, на которых будем запускать его для тестирования. Для этого заходим в каталог с установленным Android SDK (у меня это ~/necessitas/android-sdk/ ) и запускаем скрипт android из подкаталога tools.
Запустив команду Tools — Manage AVDs, можно открыть менеджер виртуальных устройств.
Мы создадим два виртуальных устройства. Одно будет с архитектурой armeabi:

.

Другое будет с архитектурой armeabi-v7a:

.

Теперь сделаем резервную копию нашего проекта и запустим Necessits QtCreator.
Прежде всего нужно зайти в Tools — Options — Android и убедиться, что всё настроено:

.

Открываем наш проект и добавляем цели сборки:

.

Жмём Finish и пробуем запустить проект.
Разумеется, сначала ничего не заработает: нужно установить прослойку Ministro, которая содержит рантайм-компоненты, необходимые для запуска Qt-приложений под Android.
Запустив виртуальное устройство, открываем браузер, вводим в поисковую строку Google «Ministro» и по второй ссылке переходим на официальный сайт, откуда скачиваем и устанавливаем последний релиз. После установки можно попробовать запустить приложение ещё раз — Ministro скачает и установит необходимые библиотеки.



Приложение запустится, но не сможет работать корректно по причине отсутствия самого главного компонента — драйвера для доступа к MySql:



Перед сборкой драйвера сначала нужно скомпилировать под Android библиотеку libmysql.
Берём исходники здесь: www.mysql.com/downloads/connector/c и распаковываем в нужную папку. Перед сборкой в папке с исходниками нужно создать файл toolchain.cmake, который описывает правила сборки под нужную нам архитектуру. Образец можно скачать, например, здесь: https://github.com/qgis/qgis-android/blob/master/scripts/android.toolchain.cmake, его нужно будет немного модифицировать:

1. В строке set( ANDROID_NDK_DEFAULT_SEARCH_PATH /path/to/android-ndk ) указать путь, по которому расположен Android-ndk.
2. В строке set( ANDROID_NDK_TOOLCHAIN_DEFAULT_SEARCH_PATH /path/to/toolchain ) указать путь, по которому расположен набор инструментов сборки.

Назовём отредактированный файл, скажем, android.cmake
Отдаём команды:

export ANDROID_NDK=/full/path/to/necessitas/android-ndk
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/mysql-connector-c-6.0.2/android.cmake
make


При сборке могут возникать некоторые легко устранимые ошибки, связанные, в основном, с отсутствием нескольких заголовочных файлов. Они легко устраняются, так что подробно останавливаться на них я не буду.
После завершения сборки в каталоге libs мы получим файл libmysql.so.16.0.0, собранный для архитектуры armeabi-v7a.

Теперь заново распаковываем исходники в другую папку, изменяем в файле android.cmake строку

set( ARM_TARGET "armeabi-v7a" CACHE STRING "the arm target for android, recommend armeabi-v7a for floating point support and NEON." )

на

set( ARM_TARGET "armeabi" CACHE STRING "the arm target for android, recommend armeabi-v7a for floating point support and NEON." )

и повторяем процедуру. Получим файл libmysql.so.16.0.0, собранный для архитектуры armeabi.
Скопируем оба варианта в удобный каталог, допустим, в ~/libs/armeabi и ~/libs/armeabi-v7a.
Теперь снова запускаем Necessitas QtCreator, открываем проект /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql/mysql.pro и добавляем цели сборки для Android:



Для сборки потребуется поместить в каталог /path/to/necessitas/Android/Qt/480/qt-src/src/sql/drivers/mysql/ следующие файлы из каталога mysql-connector-c-6.0.2/include/:
  • mysql.h
  • my_alloc.h
  • my_list.h
  • mysql_com.h
  • mysql.h
  • mysql_time.h
  • mysql_version.h
  • typelib.h

Также следует отредактировать файл qsql_mysql.h, заменив угловые скобки в инструкции #include <mysql.h> на кавычки.
Указываем цель сборки: Necessitas Qt 4.8.0 for Android armv5 Release. После этого следует подключить к проекту библиотеку mysqlclient, для чего щёлкаем правой кнопкой по корневой папке mysql, выбираем пункт «Add library». Далее выбираем External library и затем указываем путь к файлу libmysqlclient.a:



Сохраняем проект и выполняем команду Build — Build all.
В каталоге /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql-build—Necessitas_Qt_4_8_0_for_Android_armv5_Release/ получим библиотеку libqsqlmysql.so — это и есть наш долгожданный драйвер для доступа к MySQL, собранный под архитектуру armeabi.
Теперь указываем цель сборки Necessitas Qt 4.8.0 for Android armv7a Release, затем удаляем из файла mysql.pro все упоминания об lmysqlclient, и добавляем библиотеку уже для архитекутры armeabi-v7a. После сборки получим в каталоге /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql-build—Necessitas_Qt_4_8_0_for_Android_armv7a_Release/ драйвер для доступа к MySQL, собранный уже для armeabi-v7a.
Теперь можно скопировать собранные библиотеки в удобное место и снова попробовать собрать наше приложение под Android. Для этого открываем в Necessitas QtCreator наш проект-пример и добавляем к проекту зависимость от ранее скомпилированной библиотеки libqsqlmysql.so. Проще всего это сделать, добавив в *.pro-файл строчку

LIBS += -L/path/to/libs/armeabi/ -lqsqlmysql

После этого в опциях запуска приложения указываем, что необходимо закачать в эмулятор библиотеки Qt с локального компьютера.



Запускаем приложение. Если все было скомпилировано правильно, оно должно заработать:



Самое главное позади — проект успешно собран, и запускается на виртуальном устройстве.
Осталась последняя, но немаловажная часть: собрать дистрибутив приложения так, чтобы оно могло запускаться без пинка со стороны QtCreator.
К сожалению, в текущей версии necessitas имеет неприятную недоработку: дополнительные библиотеки, динамически подключаемые к приложению, не попадают в финальный дистрибутив. Обойти это можно, если зайти в каталог /path/to/project/android/res/values/ и отредактировать файл libs.xml: здесь нужно заменить массив

<array name="bundled_libs"/>

массивом следующего вида:

<array name="bundled_libs">
<item>libqsqlmysql.so</item>
</array>

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

ant clean release

После завершения сборки в подкаталоге bin каталога с проектом мы получим готовый к установке на реальное устройство apk-пакет. Аналогичным образом создаётся приложение для архитектуры armeabi-v7a.
Сергей Чернояров @kuusama
карма
8,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (14)

  • +1
    Блин код в картинках это жестковато не много, а так спасибо за статью.
    Всегда было интересно как обстоят дела у Qt и Android в реальной разработке.
  • +1
    Все хорошо и красиво, но как-то меня удивило отсутствие серверной части приложения, т.е. это получился толстый клиент, для мобильных приложений прямое соединение с базой как-бы не типично и не оптимально по архитектурным соображениям. Но решение интересное, респект.
  • 0
    А почему не в раздел Разработка под Android?
    • +1
      Вообще, мне кажется, это надо в Qt Software перенести.
    • +1
      Потому что здесь скорее «Разработка под всё», в том числе и под Android.
  • +1
    Спасибо за статью.
    Но не лучше (и проще) ли было сделать веб-прослойку с аутентификацией и соединением по HTTPS вместо прямого соединения с базой?
    • 0
      Было бы лучше, если бы программа создавалась только для Android. Наша же задача была в том, чтобы создать программу, одинаково работающую под Linux, Windows и на Android-планшете. Делать прослойку ради одного только планшета сочли нецелесообразным, тем более, что его функция заключается только в отображении данных.
      • 0
        Вы еще забыли. Работать под MacOS, maemo, Symbian, meego. Кстати, надо попробывать сбилдить mysql драйвер для Symbian, там тоже кроме sqlite ниче нет.
  • 0
    «Запустив виртуальное устройство, открываем браузер, вводим в поисковую строку Google «Ministro» и по второй ссылке переходим на официальный сайт, откуда скачиваем и устанавливаем последний релиз. После установки можно попробовать запустить приложение ещё раз — Ministro скачает и установит необходимые библиотеки.
    А насколько оно быстро вертится?
    • +1
      В эмуляторе всё работает медленно, как «родные» приложения, так и Qt-приложения, причём чем выше версия Android — тем медленнее. Поиск в Google может занять две-три минуты. На реальном же устройстве (Samsung Galaxy Mini) Qt-приложение с Ministro работает шустро, по крайней мере, мне не удалось ощутить разницу между Qt-программой и «родной».
      • 0
        Учитывая то, что Qt на С++, то еще неизвестно еще, что роднее. В теории нативный код должен работать быстрее.
  • 0
    Спасибо за статью, много полезного. А что скажете о быстродействии такого способа в реальных условия?
    • +2
      Вполне на уровне. Единственное что — Qt-приложение запускается ощутимо дольше «родного», поскольку сначала стартует прослойка Ministro.
  • 0
    Опишите еще как нормально работать с клавиатурой в necessitas этом. Чтобы нормально копировалось например. Или это нереально?

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