Qt

Creating an Android Application

This tutorial describes developing Qt Quick applications for Android devices using Qt Quick Controls.

This tutorial describes how to use Qt Creator to implement a Qt Quick application that accelerates an SVG (Scalable Vector Graphics) image based on the changing accelerometer values.

Creating the Project

Let us start with creating an empty Qt project.

  1. Select File > New File or Project > Other Project > Empty Qt Project > Choose.
  2. In the Name field, type accelbubble.
  3. In the Create in field, enter the path for the project files. For example, C:\Qt\examples, and then click Next (on Mac OS X, it is Continue).
  4. Select an Android kit for arm, and click Next.

    Note: Kits are listed if they have been specified in Tools > Options > Build & Run > Kits.

  5. Select Next in the following dialogs to use the default settings.
  6. Review the project settings, and click Finish (on Mac OS X, it is Done).

Qt Creator creates the project and displays its contents under the Projects view on the sidebar. You can only see a .pro file under the project as we created an empty project, but the remaining bits will be added during the course of this tutorial.

Creating the Main View

The main view of the application displays an SVG bubble image at the center of the main window.

  1. In the Edit mode, right-click on the accelbubble project and select Add new to open the New File dialog.
  2. Select Qt > QML File (Qt Quick 2) and click Choose to give a name to the QML file.
  3. In the Name field, type "accelbubble" and select Next.
  4. Select Finish to add accelbubble.qml to the project.

Qt Creator adds a default QML file containing a Rectangle. Here is how the QML file looks:

import QtQuick 2.0

Rectangle {
    width: 100
    height: 62
}

Now let us edit accelbubble.qml to add the bits required for our application.

  1. Replace the existing import statement with the following:
    import QtQuick 2.1
    import QtQuick.Controls 1.0
  2. Replace the Rectangle type with ApplicationWindow, which will be the top-level window for our application.
  3. Set the id, title, visible, and the window dimension properties (width and height) with the values given in the following snippet:
    ApplicationWindow {
        title: "Accelerate Bubble"
        id: mainWindow
        width: 320
        height: 480
        visible: true
    
    }

Adding an SVG Image

SVG is an XML-based image format that enables you to combine vector graphics, raster graphics, and text into one image. It is based on an open standard developed and maintained by W3C.

Qt supports the SVGT v1.2, which is a trimmed version of the SVG Full v1.2 specification, for mobile devices.

You can copy the Bluebubble.svg used by the Qt Sensors example, Accel Bubble, to your project directory or find an SVG image that uses SVGT v1.2.

Note: If you choose to create a new SVG image, ensure that the svg root element has the version attribute with the value 1.1 or 1.2, and baseProfile with tiny.

  1. Open accelbubble.qml in Edit mode and add an Image type within the ApplicationWindow.
  2. Set the image id, source, and smooth properties as shown in the following code block:
        Image {
            id: bubble
            source: "Bluebubble.svg"
            smooth: true
  3. Add the following new properties to the image:
        ...
            property real centerX: mainWindow.width / 2
            property real centerY: mainWindow.height / 2
            property real bubbleCenter: bubble.width / 2

    Note: These properties are used to position the image at the center of ApplicationWindow when the application starts.

  4. Set the x and y position of the image based on the new properties.
        ...
            x: centerX - bubbleCenter
            y: centerY - bubbleCenter
        }

Here is how the accelbubble.qml file looks after making the changes mentioned earlier in this section:

import QtQuick 2.1
import QtQuick.Controls 1.0

ApplicationWindow {
    title: "Accelerate Bubble"
    id: mainWindow
    width: 320
    height: 480
    visible: true

    Image {
        id: bubble
        source: "Bluebubble.svg"
        smooth: true
        property real centerX: mainWindow.width / 2
        property real centerY: mainWindow.height / 2
        property real bubbleCenter: bubble.width / 2
        x: centerX - bubbleCenter
        y: centerY - bubbleCenter
    }
}

Now that the visual elements are in place, let us move the bubble based on Accelerometer sensor values.

  1. Add the following import statement to accelbubble.qml:
    import QtSensors 5.0
  2. Add the Accelerometer type with the necessary properties as shown in the following code block:
        Accelerometer {
            id: accel
            dataRate: 100
            active:true
    
            }
  3. Add the following JavaScript functions that calculate the x and y position of the bubble based on the current Accelerometer values:
        function calcPitch(x, y, z) {
            return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795);
        }
        function calcRoll(x, y, z) {
             return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795);
        }
  4. Add the following JavaScript code for onReadingChanged signal of Accelerometer type to make the bubble move when the Accelerometer values change:
            onReadingChanged: {
                var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
                var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
    
                if (newX < 0)
                    newX = 0
    
                if (newX > mainWindow.width - bubble.width)
                    newX = mainWindow.width - bubble.width
    
                if (newY < 18)
                    newY = 18
    
                if (newY > mainWindow.height - bubble.height)
                    newY = mainWindow.height - bubble.height
    
                    bubble.x = newX
                    bubble.y = newY
            }
  5. Add SmoothedAnimation behavior on the x and y properties of the bubble to make its movement look smoother.
            Behavior on y {
                SmoothedAnimation {
                    easing.type: Easing.Linear
                    duration: 100
                }
            }
            Behavior on x {
                SmoothedAnimation {
                    easing.type: Easing.Linear
                    duration: 100
                }
            }

Running the Application

The main view is complete but the application is not ready yet. This section provides instructions to add a few lines of C++ code that loads the QML file when you try to run the application on an Android device.

  1. Right-click on the project in Edit mode and select Add New > Qt > Qt Resource File.
  2. Name the resource file as accelbubble.qrc and click Next.
  3. Select Finish in the following dialog to add the resource file to the project and open it in Edit mode.
  4. Select Add > Add Prefix and add / as the prefix.

    Note: The prefix is used every time you refer to the .qrc file contents from the C++ code.

  5. Select Add > Add Files and add accelbubble.qml and Bluebubble.svg to the resource file.
  6. Right-click on the project in Edit mode and select Add New to open the New File dialog.
  7. Select C++ > C++ Source File > Choose
  8. Name the file as main.cpp and click Next.
  9. Select Finish to add main.cpp to the project and open it in edit mode.
  10. Add the following lines of C++ code to main.cpp to load the accelbubble.qml file from accelbubble.qrc:
    #include <QtGui/QGuiApplication>
    #include <QtQml/QQmlApplicationEngine>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine(QUrl("qrc:///accelbubble.qml"));
    
        return app.exec();
    }
  11. Update the accelbubble.pro file with the following library dependency information:
    QT += quick sensors svg xml

The application is complete and ready to be deployed to the device. Enable "USB Debugging" on your Android device and connect it to your PC. If you are using a device running Android v4.2.2, it should prompt you to verify the connection to allow USB debugging from the PC it is connected to. To avoid such prompts every time you connect the device, check "Always allow from the computer" and select OK.

To run the application on the device, press CTRL + R keys in Qt Creator Edit mode.

Example Code

When you have completed the steps mentioned in the earlier sections, the accelbubble.qml, main.cpp, and accelbubble.pro files look as follows:

accelbubble.qml

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.1
import QtQuick.Controls 1.0

import QtSensors 5.0

ApplicationWindow {
    title: "Accelerate Bubble"
    id: mainWindow
    width: 320
    height: 480
    visible: true

    Accelerometer {
        id: accel
        dataRate: 100
        active:true

        onReadingChanged: {
            var newX = (bubble.x + calcRoll(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)
            var newY = (bubble.y - calcPitch(accel.reading.x, accel.reading.y, accel.reading.z) * 0.1)

            if (newX < 0)
                newX = 0

            if (newX > mainWindow.width - bubble.width)
                newX = mainWindow.width - bubble.width

            if (newY < 18)
                newY = 18

            if (newY > mainWindow.height - bubble.height)
                newY = mainWindow.height - bubble.height

                bubble.x = newX
                bubble.y = newY
        }
    }

    function calcPitch(x, y, z) {
        return -(Math.atan(y / Math.sqrt(x * x + z * z)) * 57.2957795);
    }
    function calcRoll(x, y, z) {
         return -(Math.atan(x / Math.sqrt(y * y + z * z)) * 57.2957795);
    }

    Image {
        id: bubble
        source: "Bluebubble.svg"
        smooth: true
        property real centerX: mainWindow.width / 2
        property real centerY: mainWindow.height / 2;
        property real bubbleCenter: bubble.width / 2
        x: centerX - bubbleCenter
        y: centerY - bubbleCenter

        Behavior on y {
            SmoothedAnimation {
                easing.type: Easing.Linear
                duration: 100
            }
        }
        Behavior on x {
            SmoothedAnimation {
                easing.type: Easing.Linear
                duration: 100
            }
        }
   }
}

main.cpp

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine(QUrl("qrc:///accelbubble.qml"));

    return app.exec();
}

accelbubble.pro

RESOURCES += \
    accelbubble.qrc

SOURCES += \
    main.cpp

QT += quick sensors svg xml