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

Flutter接收通知时如何判断应用处于已杀死还是后台状态?

解决方案:判断Firebase后台消息处理时应用是否处于已杀死状态

Flutter的firebaseMessagingBackgroundHandler运行在独立的后台Isolate中,没有直接API可以判断应用当前是后台存活还是已杀死状态,需要结合持久化状态标记、Isolate通讯检测或平台原生代码来实现,以下是几种可行方案:

方案一:基于持久化状态标记(跨平台通用,推荐)

通过监听应用生命周期,将状态保存到本地存储,在后台处理时读取状态判断。

步骤1:添加依赖

在pubspec.yaml中添加shared_preferences:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2

步骤2:前台监听生命周期并更新状态

在主应用中绑定生命周期观察者,更新本地存储的应用状态:

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  late SharedPreferences _prefs;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _initPrefs();
  }

  Future<void> _initPrefs() async {
    _prefs = await SharedPreferences.getInstance();
    // 初始化状态为前台(首次启动)
    await _prefs.setString('app_state', 'foreground');
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.resumed:
        _prefs.setString('app_state', 'foreground');
        break;
      case AppLifecycleState.paused:
        _prefs.setString('app_state', 'background');
        break;
      default:
        break;
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}

步骤3:原生监听应用终止事件(关键)

Flutter的生命周期无法捕获应用被杀死的事件,需要原生代码补充:

  • Android(MainActivity.kt):重写onTaskRemoved标记应用已杀死
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.core.content.edit
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        val prefs = getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
        prefs.edit { putString("app_state", "killed") }
    }
}
  • iOS(AppDelegate.swift):重写applicationWillTerminate标记应用已杀死
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func applicationWillTerminate(_ application: UIApplication) {
        let defaults = UserDefaults.standard
        defaults.set("killed", forKey: "app_state")
    }
}

步骤4:实现isAppKilled()方法

在后台处理函数中读取本地状态:

Future<bool> isAppKilled() async {
  final prefs = await SharedPreferences.getInstance();
  final appState = prefs.getString('app_state');
  // 状态为killed或未初始化(首次安装后直接杀死),判定为已杀死
  return appState == 'killed' || appState == null;
}

方案二:Isolate通讯检测(轻量,Android更可靠)

利用Isolate命名端口判断主Isolate是否存活:

  1. 主Isolate注册端口:
void main() async {
  await Firebase.initializeApp();
  // 注册主Isolate的控制端口
  IsolateNameServer.registerPortWithName(
    Isolate.current.controlPort, 
    'main_app_isolate'
  );
  runApp(const MyApp());
}
  1. 后台处理函数中检测端口:
Future<bool> isAppKilled() async {
  // 找不到主Isolate端口,说明应用已被杀死
  return IsolateNameServer.lookupPortByName('main_app_isolate') == null;
}

注意:iOS后台可能暂停主Isolate,会导致误判,仅推荐Android使用。

方案三:平台原生直接判断(最准确,需原生开发)

通过MethodChannel调用原生代码,直接判断应用状态:

  1. 创建MethodChannel:
const _appStateChannel = MethodChannel('com.yourpackage.app/app_state');
  1. 原生实现状态判断:
  • Android:通过ActivityManager判断是否有活跃任务
import android.app.ActivityManager
import android.content.Context
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.yourpackage.app/app_state"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "isAppKilled") {
                val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
                // 无活跃任务则判定为已杀死
                val hasActiveTasks = !activityManager.appTasks.isNullOrEmpty()
                result.success(!hasActiveTasks)
            } else {
                result.notImplemented()
            }
        }
    }
}
  • iOS:通过应用状态和启动参数判断
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    let CHANNEL = "com.yourpackage.app/app_state"

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        let controller = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { [weak self] call, result in
            if call.method == "isAppKilled" {
                // 从远程通知启动且应用状态为inactive,判定为已杀死
                let isKilled = application.applicationState == .inactive 
                    && launchOptions?[.remoteNotification] != nil
                result.success(isKilled)
            } else {
                result.notImplemented()
            }
        }
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}
  1. 实现isAppKilled():
Future<bool> isAppKilled() async {
  try {
    return await _appStateChannel.invokeMethod('isAppKilled') ?? false;
  } on PlatformException {
    return false;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:54:53