You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt Android Service多问题求助:启动延迟、崩溃、QTimer及QTcpSocket失效

Qt Android Service问题排查与修复

问题列表

  • 服务无法立即启动,存在1-2分钟延迟
  • 服务运行一段时间后停止,应用随之崩溃
  • 服务中的QTimer无法正常工作
  • QTcpSocket客户端无法正常运行(已添加android.permission.INTERNET权限)

代码与配置信息

Service的main函数代码

QTcpSocket _socket;

void onReadyRead()
{
    QByteArray datas = _socket.readAll();
    QString DataAsString = QString(datas);

    Log::log("DATA: ");
    Log::log(DataAsString);

    if(DataAsString!="HELLO\n")
        NotificationClient().setNotification(DataAsString + " BGN");
}

int main_service(int argc, char *argv[])
{
    QAndroidService app(argc, argv);

    _socket.connectToHost(QHostAddress("xx.xx.xx.xx"), 1234);
    QObject::connect(&_socket, &QTcpSocket::readyRead, onReadyRead);

    _socket.write(QByteArray("get_money()\r\n"));

    QThread::msleep(1000);

    Log::log("creating timer..");
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, someFunction);
    timer.start(500);

    //MoneyWorker *mw = new MoneyWorker();

    for(;;)
    {
        _socket.write(QByteArray("get_money()\r\n"));

        Log::log("loopin..");
        QThread::msleep(10000);
    }

    //NotificationClient().setNotification("The user is happy!");

    return app.exec();
}

启动Service的代码

QJniObject::callStaticMethod<void>(
        "org/qtproject/example/qtandroidservice/QtAndroidService",
        "startQtAndroidService",
        "(Landroid/content/Context;)V",
         QNativeInterface::QAndroidApplication::context());

Java层Service代码

package org.qtproject.example.qtandroidservice;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.qtproject.qt.android.bindings.QtService;

public class QtAndroidService extends QtService
{
    private static final String TAG = "QtAndroidService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Creating Service");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Destroying Service");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int ret = super.onStartCommand(intent, flags, startId);

        // Do some work

        return ret;
    }

    public static void startQtAndroidService(Context context) {
            context.startService(new Intent(context, QtAndroidService.class));
    }

    public static void stopQtAndroidService(Context context) {
            context.stopService(new Intent(context, QtAndroidService.class));
    }

    public static void log(String message)
    {
            Log.i(TAG, message);
    }
}

Manifest中的Service配置

<service android:name="org.qtproject.example.qtandroidservice.QtAndroidService">

adb logcat日志

08-07 22:45:15.182  5342  5366 W ActivityManager: Timeout executing service: ServiceRecord{d2392a2 u0 org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService}
08-07 22:45:15.531  5342 27607 E ActivityManager: Reason: executing service org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService
08-07 22:47:35.784  5342  5366 W ActivityManager: Timeout executing service: ServiceRecord{33bcd86 u0 org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService}
08-07 22:47:37.037  5342 29382 E ActivityManager: Reason: executing service org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService
08-07 22:47:37.121  5342  7675 W ActivityManager: Scheduling restart of crashed service org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService in 62676ms for start-requested
08-07 22:48:39.837  5342  5367 I ActivityManager: Start proc 29406:org.qtproject.example.androidnotifier/u0a477 for service {org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService}
08-07 22:48:39.982  5342  7678 W ActivityManager: Stopping service due to app idle: u0a477 -1m34s200ms org.qtproject.example.androidnotifier/org.qtproject.example.qtandroidservice.QtAndroidService
08-07 22:48:40.198 29406 29428 I QtAndroidService: creating timer..
08-07 22:48:40.198 29406 29428 I QtAndroidService: loopin..
08-07 22:48:41.199 29406 29428 I QtAndroidService: loopin..
08-07 22:48:42.200 29406 29428 I QtAndroidService: loopin..
08-07 22:48:43.201 29406 29428 I QtAndroidService: loopin..
08-07 22:48:44.201 29406 29428 I QtAndroidService: loopin..
08-07 22:48:45.202 29406 29428 I QtAndroidService: loopin..
08-07 22:48:46.203 29406 29428 I QtAndroidService: loopin..
08-07 22:48:47.204 29406 29428 I QtAndroidService: loopin..

问题根源与修复方案

1. 服务启动延迟、运行崩溃

根源:代码中的for(;;)死循环+QThread::msleep(10000)完全阻塞了Qt事件循环,app.exec()无法执行。Android系统检测到Service主线程长时间无响应(超过20秒)触发ANR,直接杀死进程,日志中的Timeout executing service就是证明,重启延迟是系统ANR后的调度策略导致。

修复:删除死循环,用QTimer实现定时请求:

// 替换原死循环代码
QTimer* requestTimer = new QTimer();
QObject::connect(requestTimer, &QTimer::timeout, [&](){
    if(_socket.state() == QAbstractSocket::ConnectedState){
        _socket.write(QByteArray("get_money()\r\n"));
        Log::log("sending request..");
    }
});
requestTimer->start(10000);

2. QTimer无法工作

根源:原代码中QTimer timer是局部栈变量,且事件循环被阻塞,导致定时器无法触发;若后续离开作用域(死循环不会,但正常流程会),定时器会被销毁。

修复:

  • 将QTimer改为堆分配(new QTimer()),避免局部变量被销毁
  • 确保app.exec()正常执行,启动Qt事件循环

3. QTcpSocket无法正常运行

根源:事件循环阻塞导致socket的connected、readyRead等信号无法处理;且connectToHost是异步操作,直接调用write时可能未建立连接,导致写入失败。

修复示例:

// 替换原socket连接代码
QObject::connect(&_socket, &QTcpSocket::connected, [&](){
    Log::log("socket connected");
    _socket.write(QByteArray("get_money()\r\n"));
});

QObject::connect(&_socket, &QTcpSocket::errorOccurred, [&](QAbstractSocket::SocketError err){
    Log::log("socket error: " + _socket.errorString());
});

_socket.connectToHost(QHostAddress("xx.xx.xx.xx"), 1234);

4. Android后台Service存活优化

根源:日志中Stopping service due to app idle说明系统因应用空闲停止服务,Android 8.0+对后台服务限制严格。

修复:

  • 在Java层Service的onStartCommand返回START_STICKY,确保服务被杀死后自动重启:
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int ret = super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }
    
  • Android 8.0+需使用前台服务,在onCreate中添加前台通知:
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Creating Service");
        
        // 创建通知渠道(Android O+必须)
        NotificationChannel channel = new NotificationChannel("service_channel", "Balance Monitor", NotificationManager.IMPORTANCE_LOW);
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);
        
        // 构建前台通知
        Notification notification = new NotificationCompat.Builder(this, "service_channel")
                .setContentTitle("Balance Monitor")
                .setContentText("Checking balance...")
                .setSmallIcon(R.mipmap.ic_launcher)
                .build();
        
        startForeground(1, notification);
    }
    
  • 在Manifest中添加前台服务权限:
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    

内容的提问来源于stack exchange,提问作者acho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:54:41