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

Flutter应用切后台返回后从闪屏重启(低端设备专属问题)

Flutter应用从第三方App返回后重启(仅低端设备出现)

用户通过Flutter应用跳转至其他App(如从Razor Pay跳转到Google Pay完成支付),返回时应用未从退出位置恢复,而是从闪屏界面重新启动。该问题仅在部分低端设备出现,高端设备运行正常,导致支付回调事件无法被监听。

问题流程

  • 用户发起购买操作
  • 弹出Razor Pay窗口,用户选择Google Pay付款渠道
  • 跳转至Google Pay完成支付
  • 返回Flutter应用时,未恢复至原页面,而是从闪屏界面重新启动

对应的AndroidManifest.xml配置

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bynge.story">
    <queries>
        <provider android:authorities="com.facebook.katana.provider.PlatformProvider" />
        <!-- allows app to access Facebook app features -->
    </queries>
    <application android:label="Notion Press" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true" android:name="com.clevertap.android.sdk.Application">
        <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="bynge_local_notification" />
        <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@mipmap/ic_launcher" />

        <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
        <activity android:name=".MainActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize" android:exported="true">
            <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" />
            <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/launch_background" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

            <!-- Deep Links -->
            <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="bynge" android:host="app" />
            </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="bynge" android:host="series" android:pathPrefix="/seriesid/episodeid" />
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="https" android:host="bynge.in" android:pathPrefix="/wa" />
            </intent-filter>
        </activity>
        <meta-data android:name="flutterEmbedding" android:value="2" />

        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
        <meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
        <activity android:name="com.facebook.FacebookActivity" android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" android:exported="true"/>
        <activity android:name="com.facebook.CustomTabActivity" 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:scheme="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>
        <activity android:name="com.yalantis.ucrop.UCropActivity" android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:exported="true"/>
        <meta-data android:name="CLEVERTAP_BACKGROUND_SYNC" android:value="1"/>
        <meta-data android:name="CLEVERTAP_NOTIFICATION_ICON" android:value="ic_launcher"/>
        <meta-data android:name="flutterEmbedding" android:value="2" />
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="com.android.vending.BILLING" />
</manifest>

解决方案

1. 调整Activity启动模式

将MainActivity的launchMode从singleTop改为singleTask,确保应用返回时复用已存在的Activity实例,避免重新创建:

android:launchMode="singleTask"

singleTask模式下,系统会保证该Activity实例唯一存在于任务栈中,从第三方App返回时直接将任务栈带到前台,不会重新启动闪屏。

2. 实现内存回收后的状态恢复

低端设备内存不足时,系统会回收后台应用进程。需在Flutter层做好状态保存:

  • 在StatefulWidget中通过saveState方法保存关键数据(如订单ID、当前路由)
  • 在initState或didChangeDependencies中检查是否有保存的状态,若存在则直接恢复到对应页面和状态

3. 正确处理支付回调

  • 在Android原生MainActivity中重写onNewIntent方法,接收第三方App返回的Intent数据,并传递给Flutter:
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    // 通过MethodChannel将支付结果传递给Flutter
    intent?.let {
        val methodChannel = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "payment_callback")
        methodChannel.invokeMethod("handlePaymentResult", it.extras)
    }
}
  • 在Flutter层监听MethodChannel回调,即使应用重启,也能通过Intent数据恢复支付状态并处理结果

4. 优化内存占用

减少应用后台时的内存消耗,降低被系统回收的概率:

  • 及时释放未使用的资源(如图片缓存、大对象)
  • 通过WidgetsBindingObserver监听应用生命周期,在进入后台时暂停不必要的任务、释放资源
  • 避免在后台运行耗时或占用内存的操作

5. 检查第三方SDK配置

确认Razor Pay SDK的回调配置正确,避免因Intent过滤问题导致返回时启动新实例:

  • 确保Razor Pay相关的Activity(若有)使用正确的启动模式
  • 检查Manifest中是否正确注册了支付回调所需的Intent Filter

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:46:02