The tutorial assumes you want to create a QML application that can be used to control the background daemon, and the daemon itself. The name of the app will be exampleapp.
Quick outlineThis is a quick outline of what has to be done, with details in later chapters:
- Create in QtCreator a subdirs project.
- Inside the subdirs project create a console application project for the daemon and a Qt Quick Application project for the UI application.
- Create a configuration file that controls launching of the daemon.
- Create aegis manifest file to set credentials for daemon.
- Create debian post-installation and before removal scripts to start the daemon after installation, and stopping the daemon before uninstallation.
Creating the basic project structure in QtCreatorThe applications submitted to Nokia store should be contained in single .deb file. To have an application that contains two binaries - the daemon and the application providing the graphical user interface - we need two different projects. We can have both a single .deb file and two different projects by creating a subdirs project.
The final project will have a file structure like this:
- exampleapp/ - exampleapp/ - exampleapp*.png - exampleapp_harmattan.desktop - exampleapp.pro - main.cpp - qml/ exampleappd/ - exampleappd.conf - exampleappd.pro - main.cpp qtc_packaging/ - debian_harmattan/ - manifest.aegis - ... + various other files
Select File - New File or Project - Other Project - Subdirs project. Give it a name, in this example it's named exampleapp. Select the compilation targets, of course at least including Harmattan. Then click Finish & Add Subproject. As you've selected Harmattan as a target, QtCreator then asks if it should include various debian packaging related files to the project. Click Yes.
Now QtCreator offers to create the first of the subprojects. We can start by creating the QML project first, although the order does not matter. Choose from the dialog Qt Quick project - Qt Quick Application. As its name give the same name as the main subdirs project's name, in this example the name will be exampleapp. Select as "Qt Quick Application Type" Qt Quick Components for Meego/Harmattan. In Target Setup dialog make sure at least Harmattan is selected.
After the graphical QML based project is created, it's time to create the daemon project. Right click on Projects view on the subdirs project and select New subproject. Choose as project template Other Project - Qt Console Application. Give it a name, in this example I enter exampleappd (postscript 'd' is a common unix convention for daemon processes). Again on Target Setup make sure Harmattan is selected.
After this you have two projects, one for the graphical user interface, and one for the daemon running in the background. You do what you do in each of them, such as communicating with each other via dbus (which is out of scope for this blog posting).
Creating daemon control fileIn order for the daemon to be started automatically on device reboots, a .conf file that is installed under
/etc/init/appsis needed. The configuration files in there are processed by Upstart (Google it for more information). Here's a bare bones version of it for the example. Create a file exampleapp/exampleappd/exampleappd.conf
description "ExampleApp daemon startup script" author "harmarto@somewherecom" stop on core_shutdown console output respawn respawn limit 3 300 normal exit 0 # This tries executing the daemon as 'user', this is # what's almost always wanted, but you also need # aegis.manifest file for that to work (shown later). exec /usr/bin/aegis-exec -s -u user /opt/exampleapp/bin/exampleappd
For more options in the configuration file and some explanations on the values used see these resources:
daemonconf.path = /etc/init/apps daemonconf.files = exampleapp.conf INSTALLS += daemonconfAs it is preferable that all your binaries are bundled in the same location (/opt/exampleapp/bin/), you need to also add this to exampleappd.pro:
target.path = /opt/exampleapp/bin INSTALLS += target
Aegis manifestOn Harmattan you will almost always want to run the daemon as user, not as a root. On Harmattan the credentials your application requests and receives from the security platform are far more important than the traditional unix root/user division. As Upstart doesn't run as 'user', you will need to request credentials for your daemon to switch to running as user. QtCreator should already have created an empty file at exampleapp/qtc_packaging/debian_harmattan/manifest.aegis. Put the following into it to get your daemon running as user:
<aegis> <request> <credential name="UID::user" /> <credential name="GID::users" /> <for path="/opt/exampleapp/bin/exampleappd"/> </request> </aegis>
Starting the daemon after installationIf you want the daemon to start after user installs your application, you need to add a script that is executed after successfull installation.
Create following file at exampleapp/qtc_packaging/debian_harmattan/postinst
#!/bin/sh set -e case "$1" in configure) echo "Starting exampleappd ..." [[ -e /etc/init/apps/exampleappd.conf ]] && initctl start apps/exampleappd ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0the initstl start command is an Upstart command to execute the commands in your exampleappd.conf file.
Stopping the daemon after uninstallingEven more important is to ensure that your daemon is stopped if user uninstalls your application. In a similar way to to running script after installing, you can instruct the system to run a script before uninstalling to stop the daemon.
Create following file exampleapp/qtc_packaging/debian_harmattan/prerm
#!/bin/sh set -e case "$1" in purge|remove|upgrade) initctl stop apps/exampleappd || true # Just in case Upstart could not stop the daemon, kill it killall exampleappd || true ;; failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0
Running from QtCreatorYou can run the resulting project from QtCreator, but it is not guaranteed that your daemon starts before the user interface application. That can be slight annoyance depending on the project. Nevertheless, when you run the application with Harmattan target, the files are installed on your device. You can then, if needed, close the user interface application, start the daemon yourself from command line by running /opt/bin/exampleapp/bin/exampleappd, and then start the UI from the application grid.
CaveatsThe daemon application must be pure console application. In other words, no graphics should be displayed by it. Trying to create any graphics context will most likely just result in abrupt termination of your daemon. There are simple ways to have daemons that can display graphics and QML, but that's a different topic if there's interest.