QtService在Android上运行应用程序后自动重启

3
我能够在这个链接中找到一个使用Qt创建Android服务的代码:link。我将服务代码放在单独的.so文件中,就像这篇文章中的代码一样。但是我有一个问题:
在启动应用程序后,服务会自动重新启动(Running services菜单中0个进程和1个服务),如图所示(MyActivities)。 MyActivities (0 processes and 1 service) 我的manifest.xml(只包含相关行):
<service android:process=":qt" android:name="org.qtproject.example.MyService">
    <!-- android:process=":qt" is needed to force the service to run on a separate process than the Activity -->

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

    <!-- If you are using the same application (.so file) for activity and also for service, then you
         need to use *android.app.arguments* to pass some arguments to your service in order to know which
         one is which.
    -->

    <!-- Application to launch -->
    <meta-data android:name="android.app.lib_name" android:value="MyService"/>
    <!-- Application to launch -->

    <!-- Ministro -->
    <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"/>
    <!-- Ministro -->

    <!-- 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"/>
    <!-- Deploy Qt libs as part of package -->

    <!-- 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%% --"/>
    <!-- Run with local libs -->

    <!--  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 -->

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

我的服务(Java部分):

package org.qtproject.example;

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 context) {
        Intent intent = new Intent(context, MyService.class);   // New Intent;
        context.startService(intent);                           // Start service;
    }
}

服务重新启动时的日志记录:

E/ActivityManager( 1553): ANR in org.qtproject.example:qt
E/ActivityManager( 1553): PID: 3006
E/ActivityManager( 1553): Reason: Executing service org.qtproject.example/.MyService
E/ActivityManager( 1553): Load: 0.59 / 0.56 / 0.24
E/ActivityManager( 1553): CPU usage from 17710ms to 0ms ago:
E/ActivityManager( 1553):   2.3% 1553/system_server: 0.9% user + 1.3% kernel / faults: 2515 minor 1 major
E/ActivityManager( 1553):   1.5% 1146/surfaceflinger: 0% user + 1.4% kernel / faults: 2 minor
E/ActivityManager( 1553):   1.4% 1668/com.android.systemui: 0.5% user + 0.9% kernel / faults: 2944 minor
E/ActivityManager( 1553):   0.3% 1150/adbd: 0% user + 0.3% kernel / faults: 176 minor
E/ActivityManager( 1553):   0.2% 2194/com.google.android.gms: 0.2% user + 0% kernel / faults: 2607 minor
E/ActivityManager( 1553):   0.1% 2761/com.android.settings: 0.1% user + 0% kernel / faults: 1130 minor
E/ActivityManager( 1553):   0.1% 1141/logd: 0% user + 0% kernel / faults: 1 minor
E/ActivityManager( 1553):   0% 1155/mediaserver: 0% user + 0% kernel / faults: 4 minor
E/ActivityManager( 1553):   0% 1724/com.google.android.gms.persistent: 0% user + 0% kernel / faults: 8 minor
E/ActivityManager( 1553):   0% 1776/com.android.phone: 0% user + 0% kernel / faults: 2 minor
E/ActivityManager( 1553):   0% 1797/com.android.launcher: 0% user + 0% kernel / faults: 607 minor
E/ActivityManager( 1553):   0% 2030/com.google.process.gapps: 0% user + 0% kernel / faults: 344 minor
E/ActivityManager( 1553):  +0% 3027/logcat: 0% user + 0% kernel
E/ActivityManager( 1553): 3.2% TOTAL: 1.1% user + 1.7% kernel + 0.1% iowait + 0.1% softirq
E/ActivityManager( 1553): CPU usage from 1336ms to 1838ms later:
E/ActivityManager( 1553):   16% 1553/system_server: 4% user + 12% kernel / faults: 15 minor
E/ActivityManager( 1553):     14% 1792/Binder_4: 2% user + 12% kernel
E/ActivityManager( 1553):   1.8% 1146/surfaceflinger: 0% user + 1.8% kernel
E/ActivityManager( 1553):     1.8% 1200/Binder_1: 0% user + 1.8% kernel
E/ActivityManager( 1553):   1.8% 2761/com.android.settings: 1.8% user + 0% kernel / faults: 8 minor
E/ActivityManager( 1553):     1.8% 2761/ndroid.settings: 0% user + 1.8% kernel
E/ActivityManager( 1553): 9.1% TOTAL: 1% user + 6.1% kernel + 2% iowait
I/ActivityManager( 1553): Killing 3006:org.qtproject.example:qt/u0a58 (adj 0): bg anr
W/libprocessgroup( 1553): failed to open /acct/uid_10058/pid_3006/cgroup.procs: No such file or directory
W/libprocessgroup( 1553): failed to open /acct/uid_10058/pid_3006/cgroup.procs: No such file or directory
W/ActivityManager( 1553): Scheduling restart of crashed service org.qtproject.example/.MyService in 43754ms
D/EGL_emulation( 1668): eglMakeCurrent: 0xb312e100: ver 2 0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for org.qtproject.example: Resource ID #0x0
W/ResourceType( 2761): No package identifier when getting value for resource number 0x00000000
W/PackageManager( 2761): Failure retrieving resources for com.google.android.gsf.login: Resource ID #0x0

在此之后,该服务将不再处于活动状态!

这张图片中的My App是我在Android Studio中编写的一个服务,它运行得非常完美。但是,在Qt中的服务存在问题。


1
为什么要对这个问题进行负评? - tulm
我似乎有完全相同的问题。在我的情况下,我有一个TCP套接字在我的服务中监听连接。如果我有解决方案,我会在这里报告。 - Ayberk Özgür
顺便提一下,我的服务不会自动重启;它只是被杀死了。 - Ayberk Özgür
2个回答

2

我曾经遇到过Qt 5.10.0的同样问题,就像你现在经历的一样,服务从未能通过onCreate()方法并很快被ANR杀死。ANR堆栈跟踪显示如下:

native: #00 pc 000174e8 /system/lib/libc.so (syscall+28)
native: #01 pc 0004777d /system/lib/libc.so (_ZL24__pthread_cond_timedwaitP23pthread_cond_internal_tP15pthread_mutex_tbPK8timespec+102)
native: #02 pc 0007888f /data/app/com.ourcompany.ourapp-1/lib/arm/libQt5Core.so (???)
native: #03 pc 0007873d /data/app/com.ourcompany.ourapp-1/lib/arm/libQt5Core.so (_ZN14QWaitCondition4waitEP6QMutexm+100)
native: #04 pc 000756cd /data/app/com.ourcompany.ourapp-1/lib/arm/libQt5Core.so (_ZN10QSemaphore7acquireEi+46)
native: #05 pc 00019975 /data/data/com.ourcompany.ourapp/qt-reserved-files/plugins/platforms/android/libqtforandroid.so (???)
at org.qtproject.qt5.android.QtNative.startQtApplication(Native method)
at org.qtproject.qt5.android.QtNative.startApplication(QtNative.java:333)
at org.qtproject.qt5.android.QtServiceDelegate.startApplication(QtServiceDelegate.java:176)
at java.lang.reflect.Method.invoke!(Native method)
at org.qtproject.qt5.android.bindings.QtLoader.loadApplication(QtLoader.java:251)
at org.qtproject.qt5.android.bindings.QtLoader.startApp(QtLoader.java:676)
at org.qtproject.qt5.android.bindings.QtServiceLoader.onCreate(QtServiceLoader.java:60)
at org.qtproject.qt5.android.bindings.QtService.onCreateHook(QtService.java:54)
at org.qtproject.qt5.android.bindings.QtService.onCreate(QtService.java:60)
at com.ourcompany.ourapp.OurService.onCreate(OurService.java:26)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3231)
at android.app.ActivityThread.-wrap5(ActivityThread.java:-1)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1597)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6236)
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)

该服务卡在等待信号量上,跟踪进一步发现,在androidjnimain.cpp的第548行调用QtAndroidPrivate::waitForServiceSetup();时发生了此等待,等待QtAndroidPrivate::g_waitForServiceSetupSemaphore被释放。这通常会在QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)中发生,该函数由QAndroidServicePrivate::QAndroidServicePrivate(QAndroidService *service)构造函数调用,后者是QAndroidService (extends QCoreApplication)的私有成员,并与之同时创建。这意味着,如果您正在本地启动服务,则绝对不应使用QCoreApplication,而应使用QAndroidService,否则您的服务将卡在此处并出现ANR。

然而,即使我使用了QAndroidService,在Qt 5.10.0中仍然存在ANR问题。在Qt 5.10.1中,我意识到调用QtAndroidPrivate::setOnBindListener(this);被替换为QTimer::singleShot(0,this, [this]{ QtAndroidPrivate::setOnBindListener(this);});,让调用在构造函数返回后发生。这似乎有效地解决了ANR问题,至少目前是这样;作为参考,我的main.cpp如下:

#include <QAndroidService>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <string.h>

int main(int argc, char** argv){

    //GUI
    if(argc <= 1){
        QGuiApplication app(argc, argv);
        qInfo() << "Service GUI starting...";
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///src/main.qml")));
        return app.exec();
    }

    //Service
    else if(argc > 1 && strcmp(argv[1], "-service") == 0){
        QAndroidService app(argc, argv);
        qInfo() << "Service starting...";

        // My service stuff

        return app.exec();
    }

    //Unrecognized argument
    else{
        qWarning() << "Unrecognized command line argument.";
        return -1;
    }
}

奇怪的是,http://code.qt.io/cgit/qt/qtandroidextras.git/tree/dist/changes-5.10.1/?h=v5.10.1 列出了“仅有轻微更改”的内容,这并不准确,因为他们显然修复了以前导致Android服务无法使用的ANR问题。
因此,解决方案似乎是使用Qt 5.10.1中的 QAndroidService 而不是 QCoreApplication

1
英雄级响应。这让我摆脱了困境。仍在努力弄清如何使服务和活动相互通信。 - Luke Dupin

0

Ayberk帮我解决了问题。

我一直在尝试使用Qt 5.12运行Android服务,已经4天了。值得一提的是:

在清单文件中..您必须将android:enabled="true"作为服务标签的一部分,例如:

<service android:process=":qt" android:enabled="true" android:name="org.qtproject.example.MyCustomAppService">

Ayberks的代码是我看到的唯一一个例子。在那之前,什么都不起作用。
此外,如果在运行qAndroidservice.exec()之前运行无限循环,Android将终止该进程,你的输出很可能无法传递到logcat。
[x] 不起作用:
qInfo() << "You should see this once for app and once for service";
if (strcmp(argv[1], "-service") == 0) {
    qInfo() << "Service is running";
    QAndroidService svc(argc, argv);
    while (true) {
        qInfo("This may or may not get displayed");
    }
    qInfo() << "This output does not display";
    return svc.exec();
}

[+] 可以工作:

qInfo() << "You should see this once for app and once for service";
if (strcmp(argv[1], "-service") == 0) {
    qInfo() << "Service is running";
    QAndroidService svc(argc, argv);
    qInfo() << "You should see this";
    return svc.exec();
}

这可能显而易见,但我尝试使用延迟在循环中重复上传GPS。这似乎很容易。我认为更好的方法是使用QTimer。因为QAndroidService确实运行,并且QWebSocket完美地工作。

其次:

qInfo和qDebug在logcat中显示。只是在QT Creators logcat中没有显示。我使用Android Studio的logcat查看器,可以看到服务的输出。

第三点:

我不知道应该把Java服务文件放在哪里。结果发现这并不是非常重要,或者我刚好把它放在了正确的位置。我将其放在/QtProjFolder/Android/src/org/qtproject/example/MyCustomAppService.java中,效果非常好。

如果有人有关于与主应用程序通信的“好”想法,请告诉我 :)

希望这能帮助大家避免像我一样浪费4天的时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接