Skip to content

Qt on Android: How to create an Android service using Qt

Starting with Qt 5.7, we added the ability to create Android services using Qt. In this article we’re going to see how to get started and also how to communicate between the two.

Before we get started I want to add a big bold WARNING about the performance! Because the services are run in the background for a very long time, make sure your service doesn’t drain the device battery!

Getting started

Step I: Extend QtService

Every single Qt Android Service must have its own Service java class which extends QtService, so the first step is to create such a service:

// java file goes in android/src/com/kdab/training/

public class MyService extends QtService

Step II: Add the service section(s) to your AndroidManifest.xml file

The next step is to add the service section(s) to your AndroidManifest.xml file. To do that you first need to copy & paste the template from to your AndroidManifest.xml file, then set android:name attribute with your service class name, as shown in the following snippet:

<application ... >
  <!-- .... -->
  <service android:process=":qt" android:name=".MyService">
  <!-- android:process=":qt" is needed to force the service to run on a separate
                                                        process than the Activity -->

    <!-- .... -->

    <!-- Background running -->
    <meta-data android:name="" android:value="true"/>
    <!-- Background running -->
  <!-- .... -->

BE AWARE: Every single Qt service/activity MUST run in it’s own process! Therefore for each service you must set a different android:process attribute value.

Step III: How to start the service ?

Now you need to decide how to start the service. There are two ways to do it:

  • on demand
  • at boot time

We’re going to check them both:

Start the service on demand

This is the most common way to start your service(s). To start the service you just need to call Context.startService(Intent intent) method. The easiest way is to add a static method to your MyService:

// java file goes in android/src/com/kdab/training/

import android.content.Context;
import android.content.Intent;

public class MyService extends QtService
    public static void startMyService(Context ctx) {
        ctx.startService(new Intent(ctx, MyService.class));

Then simply call it from Qt to start it:


Start the service at boot time

This method is used quite seldom and is useful ONLY when you really need to run the service at boot time, otherwise I do recommend you to start it on demand.

First you need to add android.permission.RECEIVE_BOOT_COMPLETED permission to your AndroidManifest.xml file:

<application ... >

  <!-- .... -->
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Then you need to add a receiver element to your AndroidManifest.xml file:

<application ... >
    <!-- .... -->
    <receiver android:name=".MyBroadcastReceiver">
            <action android:name="android.intent.action.BOOT_COMPLETED" />
    <!-- .... -->

And finally, you need to implement MyBroadcastReceiver class, as shown in the following snippet:

public class MyBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, MyService.class);

Step IV: Where to put your Qt Service code?

Next you need to decide where you’re going to put your service code. Qt (and qmake) has two options for you:

  • in the same .so file with the application
  • in a separate .so file

We’re going to check them both:

Same .so for app & service(s)

Because you’ll have one big .so file, you need a way to know when it will run as an activity or as a service. To do that you just need pass some arguments to your main function. AndroidManifest.xml allows you to easily do that:

<service ... >
    <!-- ... -->
    <!-- Application arguments -->
    <meta-data android:name="" android:value="-service"/>
    <!-- Application arguments -->
    <!-- ... -->

Then make sure you set the same metadata for both service(s) & activity elements:

<service ... >
    <!-- ... -->
    <meta-data android:name=""
                android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
    <!-- ... -->

I recommend you to use this method only if your activity and your service(s) share a large piece of code.

Separate .so files for app & service(s)

The second option is to create separate .so files for your app & service(s). First you need to create a separate server .pro file(s):

TARGET = server
CONFIG += dll
QT += core

The server .so main entry is the main function:

#include <QDebug>

int main(int argc, char *argv[])
    qDebug() << "Hello from service";
    return 0

Last you need to load the server .so file:

<service ... >
    <!-- ... -->
    <meta-data android:name="" android:value="server"/>
    <!-- ... -->

Use QtRemoteObject for communication

We’ve seen how to create and how to start a Qt on Android service, now let’s see how to do the communication between them. There are lots of solutions out there, but for any Qt project, I do recommend you use QtRemoteObject, because it will make your life so easy!

QtRemoteObjects is a playground Qt module led by Ford, for object remoting between processes/devices:

  • exports QObjects remotely (properties, signals & slots)
  • exports QAbstractItemModels remotely
  • creates a replicant on the client side you can interface with
  • repc generates source & replica (server & client) source files from .rep files
    • .rep file is the QtRemoteObjects IDL (interface description language)

As you can see it’s very Qt specific!
Let’s see how to add it to your projects and use it.

Get QtRemoteObjects

QtRemoteObjects project is located at, to get it you need to run the following commands:

$ git clone git://
$ cd qtremoteobjects
$ ~/Qt/5.7/android_armv7/bin/qmake -r && make && make install

If needed, replace ~/Qt/5.7/android_armv7 with your Qt version and android ABI of choice.

Use QtRemoteObjects

Using QtRemoteObjects is pretty easy, you need to do a few easy steps:

– add QtRemoteObjects to your .pro files

# ...
QT += remoteobjects
# ...

– create .rep file(s)

class PingPong {
    SLOT(void ping(const QString &msg));
    SIGNAL(pong(const QString &msg));

– add .rep file(s) to the server .pro file

# ...
REPC_SOURCE += pingpong.rep
# ...

– add .rep file(s) to the client .pro file

# ...
REPC_REPLICA += pingpong.rep
# ...

– QtRemoteObjects source(server) side implementation

#include <QCoreApplication>
#include "rep_pingpong_source.h"

class PingPong : public PingPongSource {
public slots:
    // PingPongSource interface
    void ping(const QString &msg) override {
        emit pong(msg + " from server");

int main(int argc, char *argv[])
    QCoreApplication app(argc, argv);

    QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
    PingPong pingPongServer;

    return app.exec();

Let’s check the code a little bit.
First you need to implement all .rep interfaces (PingPongSource), then export PingPong object using enableRemoting.

– QtRemoteObjects replica(client) side implementation

#include "rep_pingpong_replica.h"

// ....
    QRemoteObjectNode repNode;
    QSharedPointer<PingPongReplica> rep(repNode.acquire<PingPongReplica>());
    bool res = rep->waitForSource();
    QObject::connect(, &PingPongReplica::pong, [](const QString &msg){
        qDebug() << msg;
// ....

Let’s check the code:

  • use QRemoteObjectNode to connect to QRemoteObjectHost
  • use QRemoteObjectNode:acquire to link the local object to the remote one
  • use the acquired object as its local (call slots, connect to signals, etc.)

As you can see, using Qt + QtRemoteObject is (much?) easier and more straight forward than Android’s Java services + AIDL 😉


  • the activities & service(s) must run on a different process.
  • it is not possible (yet) to use QtCreator to easily add a service section to your AndroidManifest.xml file check QTCREATORBUG-16884
  • it is not possible (yet) to use QtCreator to easily generate a service subproject for us, check QTCREATORBUG-16885
  • it is not possible (yet) to see the services logs in QtCreator. You’ll need to use
     $ adb logcat 

    to see it, check QTCREATORBUG-16887

  • it is not possible (yet (hopefully)) to debug the services in QtCreator. This feature will take some time to implement it, therefore I’ll not hold my breath for it, check QTCREATORBUG-16886

Please use the above bug report links to vote for your favorite tasks, the ones that have more votes (usually) are implemented first!

You can find the full source code of this article here:

21 thoughts on “Qt on Android: How to create an Android service using Qt”

  1. Impressive!! Thanks Bogdan
    I didn’t know the QtRemoteObjects exitence, that will simplify the process a lot.

  2. Thanks for article!
    I create my own project with separate .so files for app & service similarly with your client/server example. It works nice, but I encountered some problems.

    My sequencing:
    1) client start service calling static java method with ‘startService’ command.
    2) service run lib with c++ code (specified in
    3) client and server exchange some information.
    4) client stop service calling static java method with ‘stopService’ command.

    My problems:
    1) after ‘stopService’ command java part stopped, but c++ part continues execute (I see that client/server exchange does not stopped). It’s normal behavior? Exist some simple method stop service from client fully?
    2) client subproject has access to java code and it’s work nice. But how I can access to java world from server subproject? I’m trying to add in file next code:
    QT += androidextras
    DISTFILES += android/src/
    but this java file not building and not available from c++ code.

    1. OK, for these days I found some working solutions for my troubles:
      1) When java part destroyed, I call c++ quit method with jni and thus stop c++ part.
      2) On Ubuntu I add java files to service subproject with this commands:
      ANDROID_JAVA_SOURCES.path = java/package/path
      ANDROID_JAVA_SOURCES.files = $$files(src/*.java)
      unfortunately, on Windows with mingw this commands cause an error.

  3. I have a strange error. After I start application and send some ping message to service (server), but after that, the service not working, I cannot get any pong event. When I go to setting, I saw the service restarting 0 processes and 1 service.

  4. Hello BogDan!

    Thank you so much for the article. But I have a problem. I downloaded your project from GitHub. I built and ran it. It works, but the service is killed (0 processes and 1 service) and restart after a few seconds. How I fix it?

    And do I need to install Ministro service from Google Play? (I choose option “Bundles Qt libraries in APK”).

    Thank you!

      1. Hi BogDan!

        Thanks for your answer.

        My Qt version is 5.10.1.

        Can you show me where I need to fix?

        Some additional information: the service starts when the application starts. It starts perfectly if I do not close the application. But when I close the application, the service will restart after a few seconds. After several times, it has become “Not Active”.

        Thank you very much!

        1. BogDan Vatra

          Well, that’s the correct behavior.
          Services that are not used by any application are usually closed.
          Anyway, in a couple of days I’ll retest the example and update it if needed.

          1. Thanks for your answer!

            Yes, I know that’s the correct behavior. The service can be killed by the Android OS. But when I implement a background service in Android Studio (in onStartCommand method: return START_STICKY). It works perfectly, the service still runs even if I swipe the app in the recent menu.

            Thank you very much!

  5. Hi BogDan! Thank you for the article!
    I need to implement using the same .so for app and service. I used project as base:

    The debug is not working yet, right? So to check if my .so was running as service, I tried to create a simple folder using the main.cpp code:
    if (QCoreApplication::arguments().count() > 1)
    QCoreApplication app(argc, argv);
    qDebug() << "I am the service";
    QString appFolder(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));

    return app.exec();
    But the directory was not created.

    After, I was going to check if the Java Service class was running by creating a folder from inside of its onStartCommand method:
    File dir = new File("/storage/emulated/0/TestDirectory");
    boolean successful = dir.mkdir();
    But it didn't work too!! ( I added the WRITE_EXTERNAL_STORAGE permission)
    Calling this code from the activity works…

    But using an app to check the running services, I see that the Java Service class is instantiated.

    So, my questions are:
    – Why can't I creat a directory from the Java Service class?
    – Is the .so really being started as service?

    Greetings from Brazil!

    1. It’s working now! I put the libname just like the project name.
      I recommend you to put here the main.cpp version of the same .so for service and app.

  6. Hi BogDan, I use the same .so for service and app.
    I’m trying to make Android Interprocess Communication (IPC) with Messenger between the Activity and the Service (java implementation) since they are in different processes.
    The communication is ok when I remove from the manifest this line:

    But doing that doesn’t load the .so as service, just loads the Java Service implementation.
    Is that a bug?
    It seems that is not possible to load the Java Service Implementation and the .so as service together.

    Actually, what I want is to receive the token and the messages from FCM services and process them in my .so service . It works fine in the app process, but the app process ends sometimes (causing an exception saying there is no implementation found for that native method).
    I tried to set the same process name (:qt) for the FCM services, but they crash.

    So, I want to exchange data between differents processes. Is that possible?

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to use the site, you agree to the use of cookies. More information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.