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

Qt for Android如何启动Activity并在onCreate中获取返回结果

问题根因说明

你遇到的崩溃是因为Qt业务逻辑默认运行在非Android UI线程,Android要求所有Activity操作必须在主线程执行,直接调用startActivity就会触发跨线程异常。

实现步骤

1. 项目基础配置

首先在.pro项目配置文件添加Android相关依赖:

QT += core androidextras

然后在AndroidManifest.xml里配置回调scheme,用来接收第三方应用的返回结果,在你的Activity标签内添加如下intent-filter:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:scheme="demo"
        android:host="demoresult" />
</intent-filter>

Android 11及以上版本还要在manifest根标签下添加查询声明,避免无法跳转目标应用:

<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="myapp" />
    </intent>
</queries>

2. 启动目标Activity代码

核心逻辑必须切到Android主线程执行,以下是兼容Qt5/Qt6的实现:

#include <QCoreApplication>
#include <QAndroidJniObject>
#include <QAndroidJniEnvironment>

void launchTargetApp()
{
    // 切到Android主线程执行
    QMetaObject::invokeMethod(QCoreApplication::instance(), [](){
        QAndroidJniEnvironment env;
        // 获取当前Qt Activity实例
        QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod(
            "org/qtproject/qt5/android/QtNative", 
            "activity", 
            "()Landroid/app/Activity;"
        );
        if (!activity.isValid()) return;

        // 构建目标请求Uri myapp://action
        QAndroidJniObject uriBuilder("android/net/Uri$Builder");
        uriBuilder.callObjectMethod(
            "scheme", 
            "(Ljava/lang/String;)Landroid/net/Uri$Builder;", 
            QAndroidJniObject::fromString("myapp").object<jstring>()
        );
        uriBuilder.callObjectMethod(
            "authority", 
            "(Ljava/lang/String;)Landroid/net/Uri$Builder;", 
            QAndroidJniObject::fromString("action").object<jstring>()
        );

        // 拼接请求参数
        QString packageName = QAndroidJniObject::getStaticObjectField<jstring>(
            "android/os/Build$Config", 
            "APPLICATION_ID"
        ).toString();
        uriBuilder.callObjectMethod(
            "appendQueryParameter", 
            "(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri$Builder;", 
            QAndroidJniObject::fromString("caller").object<jstring>(),
            QAndroidJniObject::fromString(packageName).object<jstring>()
        );
        uriBuilder.callObjectMethod(
            "appendQueryParameter", 
            "(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri$Builder;", 
            QAndroidJniObject::fromString("type").object<jstring>(),
            QAndroidJniObject::fromString("readNumber").object<jstring>()
        );
        uriBuilder.callObjectMethod(
            "appendQueryParameter", 
            "(Ljava/lang/String;Ljava/lang/String;)Landroid/net/Uri$Builder;", 
            QAndroidJniObject::fromString("responseUri").object<jstring>(),
            QAndroidJniObject::fromString("demo://demoresult").object<jstring>()
        );

        QAndroidJniObject targetUri = uriBuilder.callObjectMethod("build", "()Landroid/net/Uri;");
        // 创建Intent
        QAndroidJniObject actionView = QAndroidJniObject::getStaticObjectField<jstring>(
            "android/content/Intent", 
            "ACTION_VIEW"
        );
        QAndroidJniObject intent(
            "android/content/Intent", 
            "(Ljava/lang/String;Landroid/net/Uri;)V", 
            actionView.object<jstring>(), 
            targetUri.object()
        );

        // 设置启动Flag
        jint flagNewTask = QAndroidJniObject::getStaticField<jint>(
            "android/content/Intent", 
            "FLAG_ACTIVITY_NEW_TASK"
        );
        jint flagClearTask = QAndroidJniObject::getStaticField<jint>(
            "android/content/Intent", 
            "FLAG_ACTIVITY_CLEAR_TASK"
        );
        intent.callObjectMethod("setFlags", "(I)Landroid/content/Intent;", flagNewTask | flagClearTask);
        // 启动Activity
        activity.callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.object<jobject>());
    }, Qt::QueuedConnection);
}

3. 接收回调结果

方式1:Qt C++端直接读取

在应用初始化或回到前台时调用以下方法读取返回参数:

void readIntentResult()
{
    QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod(
        "org/qtproject/qt5/android/QtNative", 
        "activity", 
        "()Landroid/app/Activity;"
    );
    if (!activity.isValid()) return;
    QAndroidJniObject intent = activity.callObjectMethod("getIntent", "()Landroid/content/Intent;");
    if (!intent.isValid()) return;
    QAndroidJniObject data = intent.callObjectMethod("getData", "()Landroid/net/Uri;");
    if (data.isValid()) {
        // 替换为和第三方应用约定的返回参数key
        QAndroidJniObject result = data.callObjectMethod(
            "getQueryParameter", 
            "(Ljava/lang/String;)Ljava/lang/String;", 
            QAndroidJniObject::fromString("result").object<jstring>()
        );
        if (result.isValid()) {
            qDebug() << "返回结果:" << result.toString();
        }
    }
}

如果是应用在后台被唤起,监听QAndroidApplication::applicationStateChanged信号,在应用回到前台时重新调用该方法即可。

方式2:自定义Activity重写onCreate

如果需要更灵活的Intent处理,可以自定义Activity继承QtActivity:

package com.yourpackage.name;

import org.qtproject.qt5.android.bindings.QtActivity;
import android.os.Bundle;
import android.content.Intent;
import android.net.Uri;

public class MyCustomActivity extends QtActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        if (intent != null && intent.getData() != null) {
            Uri data = intent.getData();
            String result = data.getQueryParameter("result");
            // 可在这里做参数预处理,再传递到Qt层
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        // 处理后台唤起的新Intent
        if (intent != null && intent.getData() != null) {
            // 处理返回结果
        }
    }
}

然后在AndroidManifest.xml里把Activity的类名改为你自定义的com.yourpackage.name.MyCustomActivity即可。

注意事项
  • 所有涉及Android Activity/Intent的操作必须放在Android主线程执行,否则必然触发崩溃
  • Android 13及以上版本如果涉及跳转其他应用,需要确认目标应用已经安装,否则会启动失败
  • 回调参数的key要和第三方应用约定一致,避免读取不到返回结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:51:00