Qt6 Android Services
-
wrote on 9 Feb 2024, 01:03 last edited by
Hello,
I have already written such a post, but I deleted it since I made some changes to the main block and it also didn't get much attention. I am pretty desperate at this point since it should be something really basic, but it just doesn't work.
I want to start a background android service. In theory, as far as I am aware, according to the official documentation for android services this should happen:
main C++ function UI thread should call Java, Java should start an Qt Service calling main function again, but this time initializing the service and not the main UI thread.
Unfortunately in my case it seems the main function gets called only once, not initializing the service, because then it would call it second time. Why that is.. I do not know and have been trying to figure out for the past week..
I have simplified the code as much as I can. Here's what I have
main.cpp
#include <QApplication> #include <QtCore/QJniObject> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QUrl> #include <QNetworkAccessManager> #include <QtCore/private/qandroidextras_p.h> int main(int argc, char *argv[]) { qDebug() << "initializing main"; QApplication app(argc, argv); QNetworkAccessManager *manager = new QNetworkAccessManager; QObject::connect(manager, &QNetworkAccessManager::finished, [](QNetworkReply *reply) { qDebug() << "finished"; }); manager->get(QNetworkRequest(QUrl("http://192.168.1.10:8000/"))); QJniObject::callStaticMethod<void>( "org/qtproject/QtAndroidService", "startQtAndroidService", "(Landroid/content/Context;)V", QNativeInterface::QAndroidApplication::context()); return app.exec(); }
Here I print out in the debug terminal "initializing main", but in my terminal this is printed out only once, not twice as it is expected the android service to print it one more time. However, I have found a couple of other posts that says it won't print out anything since it is a different process, that is why I do this http request to a local server, but the server gets only one request and not two, as it is expected because the main thread and the service are both going to be able to send an http request, so that should be proof enough that the main function is not being called second time for the service.
QtAndroidService.java
package org.qtproject; import android.content.Context; import android.content.Intent; import android.util.Log; import org.qtproject.qt.android.bindings.QtService; public class QtAndroidService extends QtService { @Override public void onCreate() { Log.i("TEST", "Service onCreate"); super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("TEST", "startCommand"); int ret = super.onStartCommand(intent, flags, startId); return START_STICKY; } public static void startQtAndroidService(Context context) { Log.d("TEST", "startQtAndroidSerivce"); Intent pQtAndroidService = new Intent(context, QtAndroidService.class); pQtAndroidService.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startService(pQtAndroidService); } }
startQtAndroidService gets printed, but nothing else. This is what I see in my logs
02-09 02:46:51.388 26928 26972 D TEST : startQtAndroidSerivce 02-09 02:46:51.388 26928 26928 I HandWritingStubImpl: getCurrentKeyboardType: 1 02-09 02:46:51.419 26928 26972 D libtest1_arm64-v8a.so: finished
This libtst_arm64-v8a.so: finished might be a key part here ? Maybe this means that my process has finished for some reason, even though it looks like it never started ?
build.gradle
buildscript { repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.1.4' } } repositories { google() mavenCentral() } apply plugin: 'com.android.application' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation 'androidx.core:core:1.10.1' } android { /******************************************************* * The following variables: * - androidBuildToolsVersion, * - androidCompileSdkVersion * - qtAndroidDir - holds the path to qt android files * needed to build any Qt application * on Android. * * are defined in gradle.properties file. This file is * updated by QtCreator and androiddeployqt tools. * Changing them manually might break the compilation! *******************************************************/ compileSdkVersion androidCompileSdkVersion buildToolsVersion androidBuildToolsVersion ndkVersion androidNdkVersion sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = [qtAndroidDir + '/src', 'src', 'java'] aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl'] res.srcDirs = [qtAndroidDir + '/res', 'res'] resources.srcDirs = ['resources'] renderscript.srcDirs = ['src'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } } tasks.withType(JavaCompile) { options.incremental = true } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } packagingOptions { jniLibs { useLegacyPackaging true } } lintOptions { abortOnError false } // Do not compress Qt binary resources file aaptOptions { noCompress 'rcc' } defaultConfig { resConfig "en" namespace "org.qtproject.test1" minSdkVersion qtMinSdkVersion targetSdkVersion qtTargetSdkVersion ndk.abiFilters = qtTargetAbiList.split(",") } }
CMakeLists.txt
cmake_minimum_required(VERSION 3.16) project(test1 LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt6 COMPONENTS Widgets Core Network REQUIRED) set(PROJECT_SOURCES main.cpp ) qt_standard_project_setup() if(ANDROID) set(ANDROID_TARGET_SDK_VERSION 30) qt_add_executable(test1 MANUAL_FINALIZATION ${PROJECT_SOURCES} ) target_link_libraries(test1 PRIVATE Qt6::Widgets Qt6::Network Qt6::Core Qt6::CorePrivate) set_property(TARGET test1 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/android) qt_finalize_executable(test1) endif()
As you can see I use the corresponding versions of the following things:
Qt: 6.5
gradle: 8.1.4
java: 17
SDK version: 30Could someone please take a look or give a minimal working example ?
1/1