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

C++Builder 11.2中startActivityForResult无法触发onActivityResult问题

在C++Builder中实现Android APK安装后重启应用的正确方式

核心问题分析

你当前代码的致命问题是用while循环阻塞了UI线程:

  • Android的结果回调(对应C++Builder的TMessageResultNotification)依赖UI线程分发消息
  • while (activityResult == -1)加Sleep(100)会完全卡死UI线程,系统根本无法触发结果回调,自然永远退不出循环

另外,你自定义的onActivityResult函数没有正确关联C++Builder的消息机制,必须通过TMessageManager来接收Activity结果通知。

正确实现步骤

1. 移除阻塞UI的循环

直接删掉while循环,改用异步回调处理安装完成后的逻辑。

2. 正确订阅Activity结果消息

通过TMessageManager订阅TMessageResultNotification,在回调函数中处理安装结果。

3. 修正Intent配置

  • Android 7.0及以上版本必须用FileProvider获取文件Uri,直接用JFileToJURI会触发FileUriExposedException
  • 确保Intent的flag和参数设置正确,部分系统安装器可能不支持返回结果,可通过监听应用包安装状态处理重启。

完整代码示例

#include <System.Messaging.hpp>
#include <Androidapi.Helpers.hpp>
#include <Androidapi.JNI.GraphicsContentViewText.hpp>
#include <Androidapi.JNI.Net.hpp>
#include <Androidapi.JNI.Os.hpp>
#include <Androidapi.JNI.Content.hpp>

// 类成员变量定义
int FRequestCode = 1234;
int FMessageSubscriptionID = 0;

void __fastcall TForm5::Button3Tap(TObject *Sender, const TPointF &Point)
{
    UnicodeString filePath = _D("/storage/emulated/0/Android/data/com.embarcadero.Immixt/files/Download/Immixt.apk");

    if (!TFile::Exists(filePath))
        return;

    // 订阅Activity结果消息
    if (FMessageSubscriptionID == 0)
    {
        FMessageSubscriptionID = TMessageManager::DefaultManager->SubscribeToMessage(
            __classid(TMessageResultNotification),
            &HandleActivityResultMessage
        );
    }

    _di_JIntent installIntent = TJIntent::JavaClass->init(TJIntent::JavaClass->ACTION_INSTALL_PACKAGE);
    installIntent->addFlags(TJIntent::JavaClass->FLAG_GRANT_READ_URI_PERMISSION);
    installIntent->putExtra(TJIntent::JavaClass->EXTRA_RETURN_RESULT, true);

    // 适配Android 7+的FileProvider获取Uri
    _di_JString jFilePath = StringToJString(filePath);
    _di_JFile apkFile = TJFile::JavaClass->init(jFilePath);
    _di_Jnet_Uri apkUri;

    if (TAndroidHelper::SdkVersion >= 24)
    {
        // 使用FileProvider,需在AndroidManifest.xml中配置
        _di_JString authority = StringToJString(_D("com.embarcadero.Immixt.fileprovider"));
        apkUri = TJFileProvider::JavaClass->getUriForFile(TAndroidHelper::Context, authority, apkFile);
    }
    else
    {
        apkUri = TAndroidHelper::JFileToJURI(apkFile);
    }

    installIntent->setDataAndType(apkUri, StringToJString(_D("application/vnd.android.package-archive")));

    // 启动安装界面
    SharedActivity()->startActivityForResult(installIntent, FRequestCode);
}

void __fastcall TForm5::HandleActivityResultMessage(TObject* const Sender, TMessageBase* const M)
{
    TMessageResultNotification* msg = dynamic_cast<TMessageResultNotification*>(M);
    if (!msg || msg->RequestCode != FRequestCode)
        return;

    // 取消消息订阅
    TMessageManager::DefaultManager->Unsubscribe(__classid(TMessageResultNotification), FMessageSubscriptionID);
    FMessageSubscriptionID = 0;

    // 处理安装结果
    if (msg->ResultCode == TJActivity::JavaClass->RESULT_OK)
    {
        // 安装成功,重启应用
        RestartApp();
    }
    else if (msg->ResultCode == TJActivity::JavaClass->RESULT_CANCELED)
    {
        // 用户取消安装,可添加提示逻辑
    }
}

void __fastcall TForm5::RestartApp()
{
    // 获取当前应用的启动Intent
    _di_JPackageManager pm = TAndroidHelper::Context->getPackageManager();
    _di_JIntent launchIntent = pm->getLaunchIntentForPackage(TAndroidHelper::PackageName());
    launchIntent->addFlags(TJIntent::JavaClass->FLAG_ACTIVITY_CLEAR_TOP);
    launchIntent->addFlags(TJIntent::JavaClass->FLAG_ACTIVITY_NEW_TASK);

    // 启动应用
    TAndroidHelper::Context->startActivity(launchIntent);

    // 退出当前进程
    TJProcess::JavaClass->killProcess(TJProcess::JavaClass->myPid());
}

额外注意事项

  • FileProvider配置:Android 7+需在AndroidManifest.xml中添加配置:
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.embarcadero.Immixt.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
    
    同时在res/xml目录下创建file_paths.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-files-path name="download" path="Download/" />
    </paths>
    
  • 安装器兼容性:部分第三方安装器可能不返回RESULT_OK,可通过监听PACKAGE_ADDED广播检测安装完成,再执行重启。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:47:02