Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Android service



  • Hi,
    I am trying to implement android service.
    This service should start at boot time what is descripted on: https://www.kdab.com/qt-android-create-android-service-using-qt/
    My application is crashing and I don't know why.
    What's wrong with my code?

    Qt: 5.11.1

    Example.pro:

    TEMPLATE = subdirs
    
    SUBDIRS += Application.pro Service.pro
    

    Service.pro:

    TEMPLATE = lib
    TARGET = Service
    CONFIG += dll
    QT += core
    QT += remoteobjects
    QT += androidextras
    
    
    SOURCES += \
        sources/Service.cpp
    
    REPC_SOURCE += \
        replicas/ServiceMessenger.rep
    

    Application.pro:

    QT += quick 
    QT += remoteobjects
    QT += androidextras
    CONFIG += c++17
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which as been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
        sources/Application.cpp
    
    REPC_REPLICA += \
        replicas/ServiceMessenger.rep
    
    DISTFILES += \
        android/AndroidManifest.xml \
        android/gradle/wrapper/gradle-wrapper.jar \
        android/gradlew \
        android/res/values/libs.xml \
        android/build.gradle \
        android/gradle/wrapper/gradle-wrapper.properties \
        android/gradlew.bat \
        android/src/org/example/service/ServiceServer.java \
        android/src/org/example/service/ServiceBroadcastReceiver.java
    
    ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
    

    AndroidManifest.xml:

    <?xml version="1.0"?>
    <manifest package="org.example.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
        <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="test" android:icon="@drawable/icon">
            <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="test" android:screenOrientation="unspecified" android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
    
                <!-- Application arguments -->
                <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
                <!-- Application arguments -->
    
                <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
                <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
                <meta-data android:name="android.app.repository" android:value="default"/>
                <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
                <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
                <!-- Deploy Qt libs as part of package -->
                <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
                <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
                <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
                <!-- Run with local libs -->
                <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
                <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
                <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
                <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
                <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
                <!-- Used to specify custom system library path to run with local system libs -->
                <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
                <!--  Messages maps -->
                <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
                <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
                <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
                <!--  Messages maps -->
    
                <!-- Splash screen -->
                <!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
                <!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
                <!-- Splash screen -->
    
                <!-- Service -->
                <service android:process=":qt" android:name=".ServiceServer"/>
                <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    
                <receiver android:name=".ServiceBroadcastReceiver">
                    <intent-filter>
                        <action android:name="android.intent.action.BOOT_COMPLETED"/>
                    </intent-filter>
                </receiver>
                <!-- android:process=":qt" is needed to force the service to run on a separate
                                                            process than the Activity -->
    
                <!-- Service -->
    
                <!-- Background running -->
                <!-- Warning: changing this value to true may cause unexpected crashes if the
                              application still try to draw after
                              "applicationStateChanged(Qt::ApplicationSuspended)"
                              signal is sent! -->
                <meta-data android:name="android.app.background_running" android:value="true"/>
                <!-- Background running -->
    
                <!-- auto screen scale factor -->
                <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
                <!-- auto screen scale factor -->
    
                <!-- extract android style -->
                <!-- available android:values :
                    * full - useful QWidget & Quick Controls 1 apps
                    * minimal - useful for Quick Controls 2 apps, it is much faster than "full"
                    * none - useful for apps that don't use any of the above Qt modules
                    -->
                <meta-data android:name="android.app.extract_android_style" android:value="full"/>
                <!-- extract android style -->
        </activity>
    
        <!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
    
        </application>
    
        <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
        <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
    
        <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
             Remove the comment if you do not require these default permissions. -->
        <!-- %%INSERT_PERMISSIONS -->
    
        <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
             Remove the comment if you do not require these default features. -->
        <!-- %%INSERT_FEATURES -->
    
    
    </manifest>
    

    Application.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QAndroidJniObject>
    #include <QAndroidJniEnvironment>
    #include <QtAndroid>
    #include "rep_ServiceMessenger_replica.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
    
    	//
    	QRemoteObjectNode repNode;
        repNode.connectToNode(QUrl(QStringLiteral("local:replica")));
        QSharedPointer<ServiceMessengerReplica> rep(repNode.acquire<ServiceMessengerReplica>());
        bool res = rep->waitForSource();
        Q_ASSERT(res);
        QObject::connect(rep.data(), &ServiceMessengerReplica::pong, [](const QString &msg){
            qDebug() << "aaaaaaaaaaaaaaaaaaaaaa:" << msg;
        });
        qDebug() << "Test Test Test Test Test Test Test Test";
        rep->ping("Hello");
    	
    	//
    
        return app.exec();
    }
    

    Service.cpp:

    #include <QAndroidService>
    #include "rep_ServiceMessenger_source.h"
     
    class ServiceMessenger : public ServiceMessengerSource {
    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")));
        ServiceMessenger pingPongServer;
        srcNode.enableRemoting(&pingPongServer);
     
        return app.exec();
    }
    

    ServiceMessenger.rep:

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

    "Test Test Test Test Test Test Test Test" is not displayed.
    Error:

    Abort message:'..\service-test\sources\Application.cpp:21 ((null)): ASSERT: "res" in file ..\service-test\sources\Application.cpp, line 21
    

    Help :(


  • Lifetime Qt Champion

    Hi,

    I haven't work with QtRemoteObjects yet but some things you should do:

    • Check the return value of connectToNode
    • Connect the error signal to at least print something if it's called
    • Check lastError if the connection failed

Log in to reply