Working with databases in Qt. SQL Database Drivers


A database is a system for storing records organized in tables. A database can contain from one to several hundred tables that are interconnected. A table consists of a set of rows and columns. Table columns have names and each of them is assigned a type and/or value range. The rows of a database table are called records, and the cells into which a record is divided are called fields.

A primary key is a unique identifier that can represent not just one column, but a whole combination of columns.

The user can perform many different operations with tables, for example: adding, changing and deleting records, searching, etc. To compose this kind of queries, the SQL language (Structured Query Language, a structured query language) was developed, which makes it possible not only to carry out requests and change data, but also create new databases.

The main actions performed on the database are creating a new table, reading (selecting and projecting), inserting, modifying and deleting data. It should be said right away that language SQL is case insensitive, meaning that a letter typed in upper or lower case is considered the same. For example, SELECT = select = Select, etc. In the future, to highlight key SQL words We will use upper case.

Query language SQL is a standard that is used in large quantities DBMS, which ensures its platform independence. Queries (commands) are a kind of questions asked of the database, to which it must provide answers.

To work with a database, you must first activate the driver and then establish a connection with the database. You can then retrieve, insert, modify, and delete data using SQL queries.

Qt represents a database support module, the classes of which are divided into three levels: driver level, software level and user level. Before you can start working with the database, you need to connect to it by activating the driver. Requests are formatted as a string. The class is used to send requests QSqlQuery.

Using the Interview concept, you can easily display SQL model data in views.

Creating a table

To create a table, use the CREATE TABLE statement, which specifies the names of the table columns, their type, and also sets the primary key:

CREATE TABLE addressbook (number INTEGER PRIMARY KEY NOT NULL, name VARCHAR(15), phone VARCHAR(12), email VARCHAR(15));

Paste operation

Once the table is created, you can add data. For this SQL provides an insertion operator insert into. Immediately after the table name, you need to indicate in parentheses the names of the columns in which the data will be entered.

The data itself is indicated after the keyword values.

INSERT INTO addressbook (number, name, phone, email) VALUES(1, "Piggy", "+49 631322187", " [email protected]"); INSERT INTO addressbook (number, name, phone, email) VALUES(2, "Kermit", "+49 631322181", " [email protected]");

Reading data

Composite select statement... from ... where performs selection and projection operations. Sampling corresponds to selecting rows, and projection corresponds to selecting columns. This statement returns a table created according to the specified criteria.

  • Keyword SELECT is an operator for carrying out a projection, that is, it specifies the columns that should become the answer to the query. If you specify after SELECT*, the resulting table will contain all the columns of the table to which the query was addressed. Specifying specific column names eliminates all others from the answer.
  • Keyword FROM specifies the table to which the request is addressed.
  • Keyword WHERE is the selection operator. The sampling is carried out according to the conditions specified immediately after the operator.

For example, to get an address Email miss Piggy you need to do the following:

SELECT email FROM addressbook WHERE name = "Piggy";

Changing data

To change table data use compound operator UPDATE ... SET. After the table name in the statement SET indicate the name of the column (or columns, separated by commas) in which the data will be entered desired value. Data changes are made in rows that satisfy the condition specified in the keyword WHERE.

The example below replaces Miss Piggy's email address with [email protected] on [email protected]:

UPDATE addressbook SET email = " [email protected]" WHERE name = "Piggy";

Removal

Removing rows from a table is done using the operator DELETE ... FROM. After the keyword WHERE follows the criterion according to which rows are deleted. For example, you can remove Miss Piggy's address from the table as follows:

DELETE FROM addressbook WHERE name = "Piggy";

Qt makes it possible to create platform-independent applications for working with databases using standard DBMSs. Qt includes native drivers for Oracle, Microsoft SQL Server, Sybase Adaptive Server, IBM DB2, PostgreSQL, MySQL and ODBC compatible databases. Qt includes database-specific widgets and also supports database extension of any built-in or separately written widgets.

Introduction

Working with databases in Qt occurs at different levels:
1.Driver layer - Includes the QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin and QSqlResult classes. This layer provides a low-level bridge between specific databases and the SQL API layer.
2.SQL API Layer - This layer provides access to databases. Connections are established using the QSqlDatabase class. Interaction with the database is carried out using the QSqlQuery class. In addition to the QSqlDatabase and QSqlQuery classes, the SQL API layer relies on the QSqlError, QSqlField, QSqlIndex, and QsqlRecord classes.
3.Layer user interface- This layer connects data from the database with data-oriented widgets. This includes classes such as QSqlQueryModel, QSqlTableModel and QSqlRelationalTableModel.

Database Connection

To access a database using QSqlQuery and QSqlQueryModel, you must create and open one or more database connections.
Qt can work with the following databases (due to incompatibility with GPL license, not all plugins come with Qt Open Source Edition):
  1. QDB2 - IBM DB2 (version 7.1 and higher
  2. QIBASE - Borland InterBase
  3. QMYSQL - MySQL
  4. QOCI - Oracle Call Interface Driver
  5. QODBC - Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compatible databases
  6. QPSQL - PostgreSQL (version 7.3 and higher)
  7. QSQLITE2 - SQLite version 2
  8. QSQLITE - SQLite version 3
  9. QTDS - Sybase Adaptive Server Driver
To build a driver plugin that is not included in the Qt distribution, you need to have the appropriate client library for the DBMS you are using.

You can connect to the database like this:

  1. QSqlDatabase db = QsqlDatabase::addDatabase("QMYSQL" , "mydb" );
  2. db.setHostName("bigblue" );
  3. db.setDatabaseName("flightdb" );
  4. db.setUserName("acarlson" );
  5. db.setPassword("1uTbSbAs" );
  6. bool ok = db.open();

The first line creates a connection object, and the last line opens it. In between, some connection information is initialized, including connection name, database name, host name, user name, password. This example connects to the MySQL flightdb database on the bigblue node. The "QMYSQL" argument to addDatabase() specifies the type of database driver to use for the connection, and "mydb" is the name of the connection.
Once a connection is established, you can call the static QSqlDatabase::database() function from anywhere in the program with the name of the connection to obtain a pointer to that connection. If you do not pass a connection name, it will return the default connection.
If open() fails, it will return false. In this case, you can get information about the error by calling QSqlDatabase::lastError().
To remove a connection to a database, you must first close the database using QSqlDatabase::close(), and then remove the connection using static method QSqlDatabase::removeDatabase().

Executing SQL Statements

The QSqlQuery class provides an interface for SQL execution queries and navigation through the resulting selection.
To run SQL queries, simply create a QSqlQuery object and call QSqlQuery::exec(). For example, like this:
  1. QSqlQuery query;
  2. query.exec( "SELECT name, salary FROM employee WHERE salary > 50000");
* This source code was highlighted with Source Code Highlighter.

The QSqlQuery constructor accepts an optional QSqlDatabase argument, which specifies which database connection is being used. If you do not specify it, the default connection is used.
If an error occurs, exec() returns false. The error can be accessed using QSqlQuery::lastError().
QSqlQuery provides one-time access to the resulting selection of one query. After exec() is called, QSqlQuery's internal pointer points to the position before the first record. If you call QSqlQuery::next() once, it will move the pointer to the first record. After this, the next() call must be repeated to access other records until it returns false. Here's a typical loop that goes through all the records in order:
  1. while (query.next()) (
  2. QString name = query.value(0).toString();
  3. int salary = query.value(1).toInt();
  4. qDebug()<< name << salary;
* This source code was highlighted with Source Code Highlighter.

QSqlQuery can perform not only SELECT, but also any other queries. The following example inserts a record into a table using INSERT:
  1. QSqlQuery query;
  2. query.exec(
  3. "VALUES (1001, "Thad Beaumont", 65000)");
* This source code was highlighted with Source Code Highlighter.

If you need to insert many records at the same time, it is often more efficient to separate the query from the actual values ​​being inserted. This can be done by inserting values ​​through parameters. Qt supports two syntaxes for inserting values: named parameters and positional parameters. The following example shows insertion using a named parameter:
  1. QSqlQuery query;
  2. query.prepare( "INSERT INTO employee (id, name, salary)"
  3. "VALUES (:id, :name, :salary)");
  4. query.bindValue(":id" , 1001);
  5. query.bindValue(":name" , "Thad Beaumont" );
  6. query.bindValue(":salary" , 65000);
  7. query.exec();
* This source code was highlighted with Source Code Highlighter.

This example shows insertion using a positional parameter:
  1. QSqlQuery query;
  2. query.prepare( "INSERT INTO employee (id, name, salary)"
  3. "VALUES (?, ?, ?)" );
  4. query.addBindValue(1001);
  5. query.addBindValue("Thad Beaumont" );
  6. query.addBindValue(65000);
  7. query.exec();
* This source code was highlighted with Source Code Highlighter.

When inserting multiple records, you only need to call QSqlQuery::prepare() once. You can then call bindValue() or addBindValue() followed by exec() as many times as needed.

Displaying data in a table view

The QSqlQueryModel, QSqlTableModel and QSqlRelationalTableModel classes can be used as data sources for Qt view classes such as QListView, QTableView and QTreeView. In practice, QTableView is most commonly used due to the fact that the resulting SQL selection is essentially a two-dimensional data structure.
The following example creates a view based on a model SQL data:
  1. QSqlTableModel model;
  2. model.setTable("employee" );
  3. QTableView *view = new QTableView;
  4. view->setModel(&model);
  5. view->show();
* This source code was highlighted with Source Code Highlighter.

If the model is a read-write model (such as a QSqlTableModel), then the view allows fields to be edited. This can be disabled using the following code

Create and open one or more database connections. Database connections are normally identified by connection name, not by database name. You can have multiple connections to the same database. QSqlDatabase also supports the concept of a default connection, which is an unnamed connection. When calling QSqlQuery or QSqlQueryModel member functions that take a connection name argument, if you don"t pass a connection name, the default connection will be used. Creating a default connection is convenient when your application only requires one database connection.

Note the difference between creating a connection and opening it. Creating a connection involves creating an instance of class QSqlDatabase . The connection is not usable until it is opened. The following snippet shows how to create a default connection and then open it:

QSqlDatabase db = QSqlDatabase:: addDatabase("QMYSQL" ); db. setHostName("bigblue" ); db. setDatabaseName("flightdb" ); db. setUserName("acarlson" ); db. setPassword("1uTbSbAs" ); bool ok = db. open();

The first line creates the connection object, and the last line opens it for use. In between, we initialize some connection information, including the database name, the host name, the user name, and the password. In this case, we are connecting to the MySQL database flightdb on the host bigblue . The "QMYSQL" argument to addDatabase() specifies the type of database driver to use for the connection. The set of database drivers included with Qt are shown in the table of supported database drivers.

The connection in the snippet will be the default connection, because we don"t pass the second argument to addDatabase() , which is the connection name. For example, here we establish two MySQL database connections named "first" and "second" :

© 2019 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

Qt makes it possible to create platform-independent applications for working with databases using standard DBMSs. Qt includes native drivers for Oracle, Microsoft SQL Server, Sybase Adaptive Server, IBM DB2, PostgreSQL, MySQL and ODBC-compatible databases. Qt includes database-specific widgets and also supports database extension of any built-in or separately written widgets.

Introduction

Working with databases in Qt occurs at different levels:

1.Driver layer - Includes the QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin and QSqlResult classes. This layer provides a low-level bridge between specific databases and the SQL API layer.

2.SQL API Layer - This layer provides access to databases. Connections are established using the QSqlDatabase class. Interaction with the database is carried out using the QSqlQuery class. In addition to the QSqlDatabase and QSqlQuery classes, the SQL API layer relies on the QSqlError, QSqlField, QSqlIndex, and QsqlRecord classes.

3.User Interface Layer - This layer connects data from the database with data-oriented widgets. This includes classes such as QSqlQueryModel, QSqlTableModel and QSqlRelationalTableModel.

Database Connection

To access a database using QSqlQuery and QSqlQueryModel, you must create and open one or more database connections.

Qt can work with the following databases (due to incompatibility with the GPL license, not all plugins come with Qt Open Source Edition):

  • QDB2 - IBM DB2 (version 7.1 and higher
  • QIBASE - Borland InterBase
  • QMYSQL - MySQL
  • QOCI - Oracle Call Interface Driver
  • QODBC - Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compatible databases
  • QPSQL - PostgreSQL (version 7.3 and higher)
  • QSQLITE2 - SQLite version 2
  • QSQLITE - SQLite version 3
  • QTDS - Sybase Adaptive Server Driver

To build a driver plugin that is not included in the Qt distribution, you need to have the appropriate client library for the DBMS you are using.

You can connect to the database like this:

QSqlDatabase db = QsqlDatabase::addDatabase("QMYSQL", "mydb");

db.setHostName("bigblue");

db.setDatabaseName("flightdb");

db.setUserName("acarlson");

db.setPassword("1uTbSbAs");

bool ok = db.open();

The first line creates a connection object, and the last line opens it. In between, some connection information is initialized, including connection name, database name, host name, user name, password. This example connects to the MySQL flightdb database on the bigblue node. The "QMYSQL" argument to addDatabase() specifies the type of database driver to use for the connection, and "mydb" is the name of the connection.

Once a connection is established, you can call the static QSqlDatabase::database() function from anywhere in the program with the name of the connection to obtain a pointer to that connection. If you do not pass a connection name, it will return the default connection.

If open() fails, it will return false. In this case, you can get information about the error by calling QSqlDatabase::lastError().

To remove a connection to a database, you must first close the database using QSqlDatabase::close(), and then remove the connection using the static method QSqlDatabase::removeDatabase().

Executing SQL Statements

The QSqlQuery class provides an interface for executing SQL queries and navigating through the resulting selection. To run SQL queries, simply create a QSqlQuery object and call QSqlQuery::exec(). For example, like this:

QSqlQuery query;

query.exec("SELECT name, salary FROM employee WHERE salary > 50000");

The QSqlQuery constructor accepts an optional QSqlDatabase argument, which specifies which database connection is being used. If you do not specify it, the default connection is used. If an error occurs, exec() returns false. The error can be accessed using QSqlQuery::lastError().

QSqlQuery provides one-time access to the resulting selection of one query. After exec() is called, QSqlQuery's internal pointer points to the position before the first record. If you call QSqlQuery::next() once, it will move the pointer to the first record. After this, the next() call must be repeated to access other records until it returns false.

Here's a typical loop that goes through all the records in order:

while (query.next()) (

QString name = query.value(0).toString();

int salary = query.value(1).toInt();

qDebug()<< name << salary;

QSqlQuery can perform not only SELECT, but also any other queries. The following example inserts a record into a table using INSERT:

QSqlQuery query;

query.exec("INSERT INTO employee (id, name, salary) "

"VALUES(1001, "Thad Beaumont", 65000)");

If you need to insert many records at the same time, it is often more efficient to separate the query from the actual values ​​being inserted. This can be done by inserting values ​​through parameters. Qt supports two syntaxes for inserting values: named parameters and positional parameters. The following example shows insertion using a named parameter:

QSqlQuery query;

"VALUES (:id, :name, :salary)");

query.bindValue(":id", 1001);

query.bindValue(":name", "Thad Beaumont");

query.bindValue(":salary", 65000);

This example shows insertion using a positional parameter:

QSqlQuery query;

query.prepare("INSERT INTO employee (id, name, salary) "

"VALUES (?, ?, ?)");

query.addBindValue(1001);

query.addBindValue("Thad Beaumont");

query.addBindValue(65000);

When inserting multiple records, you only need to call QSqlQuery::prepare() once. You can then call bindValue() or addBindValue() followed by exec() as many times as needed.

Displaying data in a table view

The QSqlQueryModel, QSqlTableModel and QSqlRelationalTableModel classes can be used as data sources for Qt view classes such as QListView, QTableView and QTreeView. In practice, QTableView is most commonly used due to the fact that the resulting SQL selection is essentially a two-dimensional data structure.

The following example creates a view based on the SQL data model:

QSqlTableModel model;

model.setTable("employee");

QTableView *view = new QTableView;

view->setModel(model);

view->show();

If the model is a read-write model (such as a QSqlTableModel), then the view allows fields to be edited. This can be disabled using the following code

view->setEditTriggers(QAbstractItemView::NoEditTriggers);

You can use the same model as a data source for multiple views. If the user changes model data using one of the views, the other views will immediately reflect the changes.

The view classes for the columns at the top display the headers. To change the header text, use the setHeaderData() function of the model. For example:

model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));

model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));

model->setHeaderData(2, Qt::Horizontal, QObject::tr("City"));

model->setHeaderData(3, Qt::Horizontal, QObject::tr("Country"));

Conclusion

This article outlines the basic principles of working with databases in Qt. However, in addition to the possibilities indicated here, there are still many interesting things, for example, transactions, working with foreign keys or creating data-oriented forms. Unfortunately, these topics are quite extensive for one article.

Qt is one of the most popular and convenient development frameworks, and deservedly so. When our company received an order for a small client-server application, we did not doubt the choice of tools for a minute. The application was supposed to work on Windows and Linux, and later Android was added to the list of platforms. The application is network-based, solves a fairly simple problem, and stores all its data on the MySQL server.
And then a problem began to emerge: how to harness a Qt application, an Android application, and even make them communicate with MySQL? This article is devoted to solving this rather non-trivial problem. As an example, let's write a small application that reads strings from MySQL tables and displays them in a table field on the form.

For development we need a set gcc compilers and other development tools, the Apache ant utility, the Java compiler, the cmake utility, the MySQL DBMS server and, optionally, phpMyAdmin. Install them:

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

The remaining packages will be picked up based on their dependencies.

To develop the desktop version of the application, you will need QtSDK, the online installer of which can be downloaded from the official website: http://qt.nokia.com/downloads/.

To develop the Android version, you will need to install Necessitas, a version of Qt for Android. Necessitas includes special version QtCreator, Android SDK and Android NDK. The online installer can be found at the following address; during installation, be sure to check that the Qt source code is installed.
Now all that remains is to install the binary driver to access MySQL. It is not included in the basic Qt distribution, so it must be downloaded or compiled separately. For Ubuntu users This is not a problem: just install the libqt4-sql-mysql package:

Sudo apt-get install libqt4-sql-mysql

Then you need to copy the library to the folder with the Qt SDK installed:

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

Others will have to assemble it themselves.
After this, you can begin developing the program. First, let's open QtCreator and create an empty QtGUI project with one form:

Let's place a QTableWidget on the form and call it tw, specify the alignment of the controls on the grid.

To add MySQL support to the application, add a dependency on the QtSQL module to the project:

Let's create on MySql server sample database with a three-column tab table. Let's say the table will store the number, name and age of a person. I prefer to use phpMyAdmin for this:

Now let's add code to our application to read data from the table:

We compile, run, make sure everything works:

Our application is ready. Note that we did all this in ordinary QtCreator from the basic QtSDK package.

Now it's time to port the application to Android. First of all, we need to prepare virtual devices on which we will run it for testing. To do this, go to the directory with installed Android SDK (for me it’s ~/necessitas/android-sdk/) and run the android script from the tools subdirectory.
By running the Tools - Manage AVDs command, you can open the virtual device manager.
We will create two virtual devices. One will be with the armeabi architecture:

.

Another will be with the armeabi-v7a architecture:

.

Now let's make a backup copy of our project and launch Necessits QtCreator.
First of all, you need to go to Tools - Options - Android and make sure that everything is configured:

.

Open our project and add build targets:

.

Click Finish and try to run the project.
Of course, nothing will work at first: you need to install the Ministro layer, which contains the runtime components necessary to run Qt applications on Android.
Having launched the virtual device, open the browser, enter into the search engine Google string“Ministro” and follow the second link to the official website, from where we download and install the latest release. After installation, you can try to run the application again - Ministro will download and install the necessary libraries.

The application will start, but will not be able to work correctly due to the absence of the most important component - a driver for accessing MySql:

Before assembling the driver, you first need to compile it under Android library libmysql.
We take the sources here: www.mysql.com/downloads/connector/c and unpack them into the desired folder. Before assembling, you need to create a toolchain.cmake file in the source folder, which describes the assembly rules for the architecture we need. The sample can be downloaded, for example, here: https://github.com/qgis/qgis-android/blob/master/scripts/android.toolchain.cmake, it will need to be slightly modified:

1. In the line set(ANDROID_NDK_DEFAULT_SEARCH_PATH /path/to/android-ndk) specify the path where Android-ndk is located.
2. In the set(ANDROID_NDK_TOOLCHAIN_DEFAULT_SEARCH_PATH /path/to/toolchain) line, specify the path where the build toolset is located.

Let's call the edited file, say, android.cmake
We issue commands:

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

There may be some easily fixable errors during the build, mostly related to missing several header files. They are easily eliminated, so I will not dwell on them in detail.
After the build is completed, in the libs directory we will receive the file libmysql.so.16.0.0, compiled for the armeabi-v7a architecture.

Now we unpack the sources again into another folder, change the line in the android.cmake file

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.")

And we repeat the procedure. Let's get the file libmysql.so.16.0.0, compiled for the armeabi architecture.
Let's copy both options to a convenient directory, for example, ~/libs/armeabi and ~/libs/armeabi-v7a.
Now run Necessitas QtCreator again, open the project /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql/mysql.pro and add build targets for Android:

To build, you will need to place the following files from the mysql-connector-c-6.0.2/include/ directory in the /path/to/necessitas/Android/Qt/480/qt-src/src/sql/drivers/mysql/ directory:

  • mysql.h
  • my_alloc.h
  • my_list.h
  • mysql_com.h
  • mysql.h
  • mysql_time.h
  • mysql_version.h
  • typelib.h
You should also edit the qsql_mysql.h file, replacing the angle brackets in the #include statement in quotation marks.
Specify the build target: Necessitas Qt 4.8.0 for Android armv5 Release. After this, you should connect the mysqlclient library to the project, for which we click right click in the mysql root folder, select the “Add library” item. Next, select External library and then specify the path to the libmysqlclient.a file:

Save the project and execute the Build - Build all command.
In the directory /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql-build-Necessitas_Qt_4_8_0_for_Android_armv5_Release/ we get the libqsqlmysql.so library - this is our long-awaited driver for accessing MySQL, built under armeabi architecture.
Now we specify the build target of Necessitas Qt 4.8.0 for Android armv7a Release, then we remove all references to lmysqlclient from the mysql.pro file, and add the library for the armeabi-v7a architecture. After assembly, we will receive in the directory /path/to/necessitas/Android/Qt/480/qt-src/src/plugins/sqldrivers/mysql-build-Necessitas_Qt_4_8_0_for_Android_armv7a_Release/ a driver for accessing MySQL, already assembled for armeabi-v7a.
Now you can copy the collected libraries to a convenient place and try building our application for Android again. To do this, open our example project in Necessitas QtCreator and add to the project a dependency on the previously compiled libqsqlmysql.so library. The easiest way to do this is to add the line to the *.pro file

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

After that, in the application launch options we indicate that it is necessary to download the Qt libraries from the local computer to the emulator.

Let's launch the application. If everything was compiled correctly, it should work:

The most important thing is behind us - the project has been successfully assembled and runs on a virtual device.
The last but not least important part remains: to assemble the application distribution so that it can run without a kick from QtCreator.
Unfortunately, in the current version, necessitas has an unpleasant flaw: additional libraries that are dynamically linked to the application do not end up in the final distribution. You can get around this if you go to the /path/to/project/android/res/values/ directory and edit the libs.xml file: here you need to replace the array


an array of the following form:

libqsqlmysql.so
Since the application has already been built, all we have to do is put the specified library in the libs directory, return to the root directory of the project and issue the command in the console

Ant clean release

After the assembly is completed, in the bin subdirectory of the project directory, we will receive an apk package ready for installation on a real device. An application for the armeabi-v7a architecture is created in a similar way.







2024 gtavrl.ru.