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

Flutter中如何检测iOS设备的锁屏与解锁状态?

Detect iOS Lock/Unlock State in Flutter (Without App Lifecycle Methods)

Got it, since the screen_state plugin only works on Android and you need to detect actual lock/unlock events on iOS (not just app lifecycle changes), here's how you can implement this using Flutter's MethodChannel to bridge to iOS native APIs that specifically track these system events:

Step 1: Set Up the MethodChannel in Flutter

First, create a helper class in Flutter to handle communication with the iOS native layer and expose a stream for lock state updates:

import 'package:flutter/services.dart';

class LockStateDetector {
  static const MethodChannel _channel = MethodChannel('lock_state_channel');
  static final StreamController<bool> _lockStateController = StreamController.broadcast();

  // Stream to subscribe for lock/unlock state changes
  static Stream<bool> get lockStateStream => _lockStateController.stream;

  static Future<void> initialize() async {
    // Listen for messages from iOS
    _channel.setMethodCallHandler((call) async {
      if (call.method == 'onLockStateChanged') {
        final bool isLocked = call.arguments as bool;
        _lockStateController.add(isLocked);
      }
    });
    // Tell iOS to start listening for lock events
    await _channel.invokeMethod('startListening');
  }

  // Clean up resources when done
  static void dispose() {
    _lockStateController.close();
  }
}

Step 2: Implement iOS Native Listener

On iOS, we'll use system notifications that specifically trigger for lock/unlock actions (not app backgrounding). These are UIProtectedDataWillBecomeUnavailableNotification (locks) and UIProtectedDataDidBecomeAvailableNotification (unlocks) — these are tied to the device's security state, so they won't fire when the app is just minimized.

Update AppDelegate.swift (iOS Runner):

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  private let channelName = "lock_state_channel"
  private var flutterChannel: FlutterMethodChannel!

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller = window?.rootViewController as! FlutterViewController
    flutterChannel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
    
    // Handle Flutter's request to start listening
    flutterChannel.setMethodCallHandler { [weak self] call, result in
      guard let self = self else { return }
      if call.method == "startListening" {
        self.setupLockStateListeners()
        result(nil)
      } else {
        result(FlutterMethodNotImplemented)
      }
    }

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  private func setupLockStateListeners() {
    // Listen for device lock event
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(onDeviceLocked),
      name: UIApplication.protectedDataWillBecomeUnavailableNotification,
      object: nil
    )
    
    // Listen for device unlock event
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(onDeviceUnlocked),
      name: UIApplication.protectedDataDidBecomeAvailableNotification,
      object: nil
    )
  }

  @objc private func onDeviceLocked() {
    flutterChannel.invokeMethod("onLockStateChanged", arguments: true)
  }

  @objc private func onDeviceUnlocked() {
    flutterChannel.invokeMethod("onLockStateChanged", arguments: false)
  }

  // Clean up observers when the delegate is deinitialized
  deinit {
    NotificationCenter.default.removeObserver(self)
  }
}

Step 3: Use the Detector in Your Flutter App

Now you can subscribe to the lock state stream in any Flutter widget to react to lock/unlock events:

class LockMonitorPage extends StatefulWidget {
  const LockMonitorPage({super.key});

  @override
  State<LockMonitorPage> createState() => _LockMonitorPageState();
}

class _LockMonitorPageState extends State<LockMonitorPage> {
  bool _isDeviceLocked = false;

  @override
  void initState() {
    super.initState();
    // Initialize the detector
    LockStateDetector.initialize();
    // Subscribe to lock state updates
    LockStateDetector.lockStateStream.listen((isLocked) {
      setState(() {
        _isDeviceLocked = isLocked;
      });
    });
  }

  @override
  void dispose() {
    LockStateDetector.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Device Lock State")),
      body: Center(
        child: Text(
          _isDeviceLocked ? "Device is Locked" : "Device is Unlocked",
          style: const TextStyle(fontSize: 20),
        ),
      ),
    );
  }
}

Key Details

  • Why These Notifications?: Unlike app lifecycle events, the UIProtectedData notifications are directly tied to the device's security state. They only trigger when the device is locked/unlocked, not when the app is sent to the background by the user.
  • Permissions: No extra iOS permissions are needed to use these notifications.
  • Memory Management: Always remember to clean up the notification observers in iOS and close the Flutter StreamController to avoid memory leaks.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:33:11