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

如何让Delphi开发的Android应用后台恢复时不重启

问题翻译(中文)

我用Delphi开发了一款Android应用,启动应用并通过Intent唤起另一款应用后,关闭第二个应用返回第一个应用时,第一个应用会重启。我知道onSaveState相关机制,但我需要应用不重启——因为要用到第二个应用返回的数据。我通过Intent启动第二个应用,关闭它后应该回到第一个应用能处理返回Intent的状态,但实际却是重启了。

更新:以下是我的代码:

procedure TForm1.btnEnviarTransacaoClick(Sender: TObject);
begin
   try
      var AURI:string:= 'payment-app://pay?return_scheme=retorno&amount=9999&editable_amount=0&transaction_type=credit';
      var AIntent: JIntent := TJIntent.Create;
      AIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW);
      AIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
      AIntent.setData(TJNet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(AURI))));
      TAndroidHelper.Activity.startActivityForResult(AIntent, 0);
      Timer1.Enabled:= True;
   except
      on E: Exception do begin
         TThread.Synchronize(nil, procedure
         begin
            lOG.D(E.Message);
         end);
      end;
   end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   Timer1.Enabled:= False;
   var ADLg:= TForm2.Create(Self);
   ADLg.Show;
end;

注:启动第二个Activity后,我触发了一个4秒的定时器来创建并显示Form2,但结束第二个应用返回主应用时,主应用会重启。调试时偶尔会捕获到异常:

cant perform this action after onSaveInstanceState

这是我的AndroidManifest,其中通过Scheme使用显式Intent:

<activity
    android:name=".PaymentActivity"
    android:launchMode="singleTop"
    android:exported="true">
    <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:host="pay-response"
            android:scheme="retorno" />
    </intent-filter>
</activity>

问题分析与解决办法

1. 移除错误的Intent Flag

你给Intent添加了FLAG_ACTIVITY_NEW_TASK,但调用startActivityForResult时完全不需要这个Flag——当前Activity已经处于任务栈中,添加该Flag会强制将第二个应用启动到新任务栈,返回时系统可能会重建原Activity,直接触发重启。

修改代码,删除这一行:

AIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);

2. 废弃定时器逻辑,改用onActivityResult处理返回

定时器触发时,原Activity大概率已经执行了onSaveInstanceState(启动第二个应用后,原Activity会进入后台并保存状态),此时调用Show显示Form2会触发cant perform this action after onSaveInstanceState异常,这正是应用重启的直接原因。

正确做法是重写onActivityResult方法,在第二个应用返回后再处理数据并显示Form2:

首先在Form1的类声明中添加重写方法:

type
  TForm1 = class(TForm)
    btnEnviarTransacao: TButton;
    Timer1: TTimer;
    procedure btnEnviarTransacaoClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    procedure ActivityResult(RequestCode, ResultCode: Integer; Data: JIntent); override;
  public
    { Public declarations }
  end;

然后实现该方法:

procedure TForm1.ActivityResult(RequestCode, ResultCode: Integer; Data: JIntent);
begin
  inherited;
  if RequestCode = 0 then // 对应startActivityForResult的请求码
  begin
    if ResultCode = TJActivity.JavaClass.RESULT_OK then
    begin
      // 处理第二个应用返回的数据,示例:获取返回的Uri
      if Assigned(Data) and Assigned(Data.getData) then
      begin
        var ReturnUri := JStringToString(Data.getData.toString);
        // 这里添加数据处理逻辑
      end;
      // 此时Activity处于活跃状态,安全显示Form2
      var ADLg := TForm2.Create(Self);
      ADLg.Show;
    end;
  end;
end;

同时删除btnEnviarTransacaoClick中的定时器启动代码:

// Timer1.Enabled:= True; // 删掉这一行

3. 调整Activity启动模式与Intent Filter

确保主应用的主Activity(非PaymentActivity)的launchMode设置为singleTop或standard(避免singleTask等可能导致重建的模式),同时给主Activity添加接收返回Scheme的Intent Filter,保证返回数据能正确传递到原Activity:

<!-- 主应用主Activity的配置 -->
<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    android:exported="true">
    <!-- 原有启动入口Filter -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <!-- 添加接收返回Scheme的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:host="pay-response"
            android:scheme="retorno" />
    </intent-filter>
</activity>

4. 禁止后台状态下的UI操作

永远不要在Activity可能进入后台后(比如调用startActivity之后),通过定时器、异步回调等方式执行UI操作——此时Activity可能已被系统回收,或处于状态已保存的不可修改状态,极易引发异常和重启。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:14:52