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是否存活:
- 主Isolate注册端口:
void main() async { await Firebase.initializeApp(); // 注册主Isolate的控制端口 IsolateNameServer.registerPortWithName( Isolate.current.controlPort, 'main_app_isolate' ); runApp(const MyApp()); }
- 后台处理函数中检测端口:
Future<bool> isAppKilled() async { // 找不到主Isolate端口,说明应用已被杀死 return IsolateNameServer.lookupPortByName('main_app_isolate') == null; }
注意:iOS后台可能暂停主Isolate,会导致误判,仅推荐Android使用。
方案三:平台原生直接判断(最准确,需原生开发)
通过MethodChannel调用原生代码,直接判断应用状态:
- 创建MethodChannel:
const _appStateChannel = MethodChannel('com.yourpackage.app/app_state');
- 原生实现状态判断:
- 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) } }
- 实现
isAppKilled():
Future<bool> isAppKilled() async { try { return await _appStateChannel.invokeMethod('isAppKilled') ?? false; } on PlatformException { return false; } }
内容的提问来源于stack exchange,提问作者Chapo144
相关产品推荐
相关产品推荐

