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
相关产品推荐
相关产品推荐

