Better_Software_Header_MobileBetter_Software_Header_Web

Find what you need - explore our website and developer resources

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

Full code samples for building with and communicating to QAndroidService background tasks

// java file goes in android/src/com/kdab/training/MyService.java
package com.kdab.training;
import org.qtproject.qt5.android.bindings.QtService;

public class MyService extends QtService
{
}
<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.app.background_running" android:value="true"/>
    <!-- Background running -->
  </service>
  <!-- .... -->
</application>
// java file goes in android/src/com/kdab/training/MyService.java
package com.kdab.training;

import android.content.Context;
import android.content.Intent;
import org.qtproject.qt5.android.bindings.QtService;

public class MyService extends QtService
{
    public static void startMyService(Context ctx) {
        ctx.startService(new Intent(ctx, MyService.class));
    }
}
QAndroidJniObject::callStaticMethod<void>("com/kdab/training/MyService",
                                              "startMyService",
                                              "(Landroid/content/Context;)V",
                                              QtAndroid::androidActivity().object());
<application ... >

  <!-- .... -->
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</application>
<application ... >
    <!-- .... -->
    <receiver android:name=".MyBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <!-- .... -->
</application>
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, MyService.class);
        context.startService(startServiceIntent);
    }
}
<service ... >
    <!-- ... -->
    <!-- Application arguments -->
    <meta-data android:name="android.app.arguments" android:value="-service"/>
    <!-- Application arguments -->
    <!-- ... -->
</service>
<service ... >
    <!-- ... -->
    <meta-data android:name="android.app.lib_name"
                android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
    <!-- ... -->
</service>
TEMPLATE = lib
TARGET = server
CONFIG += dll
QT += core
SOURCES += \
    server.cpp
#include <QDebug>

int main(int argc, char *argv[])
{
    qDebug() << "Hello from service";
    return 0
}
<service ... >
    <!-- ... -->
    <meta-data android:name="android.app.lib_name" android:value="server"/>
    <!-- ... -->
</service>
$ git clone git://code.qt.io/qt/qtremoteobjects.git
$ cd qtremoteobjects
$ ~/Qt/5.10.1/android_armv7/bin/qmake -r && make && make install
# ...
QT += androidextras
QT += remoteobjects
# ...
class PingPong {
    SLOT(void ping(const QString &msg));
    SIGNAL(pong(const QString &msg));
}
# ...
REPC_SOURCE += pingpong.rep
# ...
# ...
REPC_REPLICA += pingpong.rep
# ...
#include <QAndroidService>
#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[])
{
    QAndroidService app(argc, argv);

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

    return app.exec();
}
#include "rep_pingpong_replica.h"

// ....
    QRemoteObjectNode repNode;
    repNode.connectToNode(QUrl(QStringLiteral("local:replica")));
    QSharedPointer<PingPongReplica> rep(repNode.acquire<PingPongReplica>());
    bool res = rep->waitForSource();
    Q_ASSERT(res);
    QObject::connect(rep.data(), &PingPongReplica::pong, [](const QString &msg){
        qDebug() << msg;
    });
    rep->ping("Hello");
// ....

68 Comments

29 - Sept - 2016

l2m

29 - Sept - 2016

euge

2 - Oct - 2016

Bernhard

5 - Oct - 2016

Patricia Gulotta

20 - Oct - 2016

Sergey

26 - Oct - 2016

Sergey

11 - Dec - 2016

Amr

11 - Dec - 2016

Amr

26 - Jan - 2018

BogDan Vatra

13 - Dec - 2016

lyn

26 - Jan - 2018

BogDan Vatra

9 - Feb - 2018

Le Minh Tu

24 - Feb - 2018

tulm

26 - Feb - 2018

BogDan Vatra

26 - Feb - 2018

tulm

26 - Feb - 2018

BogDan Vatra

26 - Feb - 2018

tulm

3 - Mar - 2018

Jhones Santos

if (QCoreApplication::arguments().count() > 1)
    {
        QCoreApplication app(argc, argv);
        qDebug() << "I am the service";
        QString appFolder(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
        QDir(appFolder).mkdir("Testing");

        return app.exec();
    }
File dir = new File("/storage/emulated/0/TestDirectory");
boolean successful = dir.mkdir();

3 - Mar - 2018

Jhones Santos

6 - Mar - 2018

Jhones

6 - Mar - 2018

Jhones

26 - Apr - 2018

george

#ifdef Q_OS_ANDROID
    QAndroidJniObject titleObj = QAndroidJniObject::fromString(title);
    QAndroidJniObject notificationObj = QAndroidJniObject::fromString(notification);
    QAndroidJniObject acceptLabelObj = QAndroidJniObject::fromString(acceptLabel);
    QAndroidJniObject rejectLabelObj = QAndroidJniObject::fromString(rejectLabel);
    QAndroidJniObject::callStaticMethod("com/HSEManagementSoftwareSolutions/HSEManagementSoftwareSolutions/ApplicationService",
                                              "sendNormalNotification",
                                              "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V",
                                              titleObj.object(),
                                              notificationObj.object(),
                                              notification_code,
                                              acceptLabelObj.object(),
                                              rejectLabelObj.object());
    #endif
package com.HSEManagementSoftwareSolutions.HSEManagementSoftwareSolutions;

import org.qtproject.qt5.android.bindings.QtService;
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
import android.media.RingtoneManager;
import com.HSEManagementSoftwareSolutions.HSEManagementSoftwareSolutions.R;
import android.graphics.Color;

public class ApplicationService extends QtService
{
    private static ApplicationService applicationServiceInstance;
    private static NotificationManager notificationManager;
    private static Notification.Builder notificationBuilder;

    static final String packageName = "com.HSEManagementSoftwareSolutions.HSEManagementSoftwareSolutions";
    static final String appName = "HSE Management Software Solutions";

    public ApplicationService()
    {
        applicationServiceInstance = this;
    }

    public static void startApplicationService(Context applicationContext)
    {
        applicationContext.startService(new Intent(applicationContext,ApplicationService.class));
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
    }

    static void sendNormalNotification(String title,String notification,int notification_code,String acceptLabel,String rejectedLabel)
    {
        notificationManager = (NotificationManager) applicationServiceInstance.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationBuilder = new Notification.Builder(applicationServiceInstance);
        notificationBuilder.setSmallIcon(R.drawable.icon);
        notificationBuilder.setContentTitle(title);
        notificationBuilder.setContentText(notification);
        notificationBuilder.setAutoCancel(true);
        notificationBuilder.setPriority(Notification.PRIORITY_HIGH);
        notificationBuilder.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 });
        notificationBuilder.setLights(Color.RED, 3000, 3000);
        notificationBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
        notificationBuilder.addAction(R.drawable.yesicon,acceptLabel,PendingIntent.getActivity(applicationServiceInstance,0,new Intent(applicationServiceInstance, ApplicationActivity.class), PendingIntent.FLAG_UPDATE_CURRENT));
        notificationBuilder.addAction(R.drawable.noicon,rejectedLabel,PendingIntent.getBroadcast(applicationServiceInstance.getApplicationContext(),0,new Intent("com.HSEManagementSoftwareSolutions.HSEManagementSoftwareSolutions.NotificationCancled").putExtra("notification_id",notification_code),PendingIntent.FLAG_CANCEL_CURRENT));
        notificationManager.notify(notification_code,notificationBuilder.build());
    }
}

6 - Mar - 2019

BogDan Vatra

4 - Feb - 2019

Manasa

6 - Mar - 2019

BogDan Vatra

7 - May - 2020

Mike Inman

27 - May - 2020

BogDan Vatra

9 - Apr - 2019

E.T.

15 - Apr - 2019

BogDan Vatra

27 - Apr - 2019

Shujaat

6 - May - 2019

BogDan Vatra

15 - May - 2019

gndz

26 - Jun - 2019

Catalin Prata

23 - Aug - 2019

Pieter Jordaan

23 - Aug - 2019

BogDan Vatra

26 - Aug - 2019

Sam Grant

4 - Dec - 2019

Oles

        QAndroidJniObject::callStaticMethod("org/qtproject/example/neoclient/MainNotifyService",
                                                  "stopService",
                                                  "(Landroid/content/Context;)V",
                                                  QtAndroid::androidActivity().object());

8 - Jan - 2020

Avtem

26 - Feb - 2020

BogDan Vatra

1 - Apr - 2020

Thibaud Kloczko

5 - May - 2020

BogDan Vatra

2 - Jul - 2020

Kastuś Kalinoŭski

19 - Jul - 2020

BogDan Vatra

20 - Aug - 2020

Mikael

W System.err: java.lang.IllegalArgumentException: Wrong number of arguments; expected 1, got 0
W System.err:   at java.lang.reflect.Method.invoke(Native Method)
W System.err:   at org.qtproject.qt5.android.bindings.QtApplication.invokeDelegateMethod(QtApplication.java:157)
W System.err:   at org.qtproject.qt5.android.bindings.QtServiceLoader.onCreate(QtServiceLoader.java:59)
W System.err:   at org.qtproject.qt5.android.bindings.QtService.onCreateHook(QtService.java:54)
W System.err:   at org.qtproject.qt5.android.bindings.QtService.onCreate(QtService.java:60)
W System.err:   at android.app.ActivityThread.handleCreateService(ActivityThread.java:3756)
W System.err:   at android.app.ActivityThread.access$1400(ActivityThread.java:237)
W System.err:   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1801)
W System.err:   at android.os.Handler.dispatchMessage(Handler.java:106)
W System.err:   at android.os.Looper.loop(Looper.java:214)
W System.err:   at android.app.ActivityThread.main(ActivityThread.java:7050)
W System.err:   at java.lang.reflect.Method.invoke(Native Method)
W System.err:   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
W System.err:   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
W System  : ClassLoader referenced unknown path:

2 - Apr - 2020

Matthieu

E m.kdab.trainin: Invalid ID 0x00000000.
E Qt      : Can't create main activity
E Qt      : android.content.res.Resources$NotFoundException: String array resource ID #0x0
E Qt      :     at android.content.res.Resources.getStringArray(Resources.java:597)
E Qt      :     at android.content.res.MiuiResources.getStringArray(MiuiResources.java:160)
E Qt      :     at org.qtproject.qt5.android.bindings.QtLoader.startApp(QtLoader.java:423)
E Qt      :     at org.qtproject.qt5.android.bindings.QtActivityLoader.onCreate(QtActivityLoader.java:166)
E Qt      :     at org.qtproject.qt5.android.bindings.QtActivity.onCreateHook(QtActivity.java:266)
E Qt      :     at org.qtproject.qt5.android.bindings.QtActivity.onCreate(QtActivity.java:273)
E Qt      :     at android.app.Activity.performCreate(Activity.java:7224)
E Qt      :     at android.app.Activity.performCreate(Activity.java:7213)
E Qt      :     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
E Qt      :     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
E Qt      :     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
E Qt      :     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
E Qt      :     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
E Qt      :     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
E Qt      :     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
E Qt      :     at android.os.Handler.dispatchMessage(Handler.java:106)
E Qt      :     at android.os.Looper.loop(Looper.java:201)
E Qt      :     at android.app.ActivityThread.main(ActivityThread.java:6810)
E Qt      :     at java.lang.reflect.Method.invoke(Native Method)
E Qt      :     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
E Qt      :     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
W Looper  : Slow Looper main: Activity com.kdab.training/org.qtproject.qt5.android.bindings.QtActivity is 7754ms late (wall=596ms running=0ms ClientTransaction{ callbacks=[android.app.servertransaction.LaunchActivityItem] lifecycleRequest=android.app.servertransaction.ResumeActivityItem }) because of 1 msg, msg 1 took 7849ms (late=1ms h=android.app.ActivityThread$H w=110)

5 - May - 2020

BogDan Vatra

2 - Apr - 2020

Thibaud Kloczko

14 - Jul - 2020

Maxim B.

19 - Jul - 2020

BogDan Vatra

10 - Aug - 2020

Mihail

10 - Aug - 2020

BogDan Vatra

10 - Aug - 2020

Mihail

12 - Aug - 2020

Maxim

15 - Aug - 2020

Maxim B.

17 - Aug - 2020

BogDan Vatra

23 - Aug - 2020

Maxim B.

24 - Aug - 2020

Maxim B.

25 - Aug - 2020

BogDan Vatra

31 - Aug - 2020

Maxim B.

19 - Jan - 2021

BogDan Vatra

9 - Nov - 2020

Toni E.

1 - Jul - 2021

Bruce

24 - Sept - 2021

Mehran

24 - Sept - 2021

BogDan Vatra

24 - Sept - 2021

Mehran

6 - Aug - 2023

Chris Sparks

23 - Oct - 2023

Loren Burkholder

14 - Nov - 2023

han