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

Flutter如何实现仅指定页面在手机锁屏状态下可见

Flutter实现单页面锁屏可访问,其他页面保持锁定

针对你的需求,我们可以通过Flutter与原生平台通信的方式,动态控制页面的锁屏访问权限,无需修改Flutter单Activity架构,仅让SecondScreen在锁屏状态下可操作,其他页面保持正常锁定。


Android 端实现步骤

1. 恢复AndroidManifest默认配置

移除之前添加的全局android:showWhenLocked="true"和android:turnScreenOn="true"属性,保持MainActivity配置默认。

2. Flutter 端修改SecondScreen

通过MethodChannel与原生通信,在页面进入时开启锁屏访问权限,页面销毁时关闭:

class _SecondScreenState extends State<SecondScreen> {
  static const MethodChannel _lockChannel = MethodChannel('lock_screen_control');

  @override
  void initState() {
    super.initState();
    // 页面进入时启用锁屏访问
    _enableLockScreenAccess();
  }

  @override
  void dispose() {
    // 页面销毁时关闭锁屏访问
    _disableLockScreenAccess();
    super.dispose();
  }

  Future<void> _enableLockScreenAccess() async {
    try {
      await _lockChannel.invokeMethod('enable');
    } on PlatformException catch (e) {
      print('开启锁屏访问失败: ${e.message}');
    }
  }

  Future<void> _disableLockScreenAccess() async {
    try {
      await _lockChannel.invokeMethod('disable');
    } on PlatformException catch (e) {
      print('关闭锁屏访问失败: ${e.message}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SECOND SCREEN')),
      body: const Center(
        child: Text('THIS IS SECOND SCREEN THAT SHOULD BE ACCESSIBLE EVEN WHEN PHONE IS LOCKED'),
      ),
    );
  }
}

3. Android 原生代码实现权限控制

修改MainActivity.kt(或Java版本),实现MethodChannel的方法处理:

Kotlin版本

import android.os.Build
import android.view.WindowManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "lock_screen_control"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "enable" -> {
                    enableLockScreenAccess()
                    result.success(null)
                }
                "disable" -> {
                    disableLockScreenAccess()
                    result.success(null)
                }
                else -> result.notImplemented()
            }
        }
    }

    private fun enableLockScreenAccess() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
        } else {
            window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            )
        }
    }

    private fun disableLockScreenAccess() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(false)
            setTurnScreenOn(false)
        } else {
            window.clearFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            )
        }
    }
}

Java版本

import android.os.Build;
import android.view.WindowManager;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "lock_screen_control";

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler((call, result) -> {
                    switch (call.method) {
                        case "enable":
                            enableLockScreenAccess();
                            result.success(null);
                            break;
                        case "disable":
                            disableLockScreenAccess();
                            result.success(null);
                            break;
                        default:
                            result.notImplemented();
                    }
                });
    }

    private void enableLockScreenAccess() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true);
            setTurnScreenOn(true);
        } else {
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            );
        }
    }

    private void disableLockScreenAccess() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(false);
            setTurnScreenOn(false);
        } else {
            getWindow().clearFlags(
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            );
        }
    }
}

iOS 端实现步骤

1. Flutter 端代码复用

直接使用上面修改后的SecondScreen代码,无需额外改动。

2. iOS 原生代码实现权限控制

修改AppDelegate.swift,处理MethodChannel调用:

import UIKit
import Flutter
import UserNotifications

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    private let CHANNEL = "lock_screen_control"
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        let methodChannel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)
        
        methodChannel.setMethodCallHandler { [weak self] call, result in
            guard let self = self else { return }
            switch call.method {
            case "enable":
                self.enableLockScreenAccess()
                result.success(nil)
            case "disable":
                self.disableLockScreenAccess()
                result.success(nil)
            default:
                result.notImplemented()
            }
        }
        
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    private func enableLockScreenAccess() {
        // 防止屏幕自动休眠
        UIApplication.shared.isIdleTimerDisabled = true
        // 发送静默通知唤醒锁屏状态的屏幕
        let content = UNMutableNotificationContent()
        content.title = ""
        content.body = ""
        content.sound = .none
        let request = UNNotificationRequest(identifier: "wake_screen", content: content, trigger: nil)
        UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
                print("唤醒屏幕失败: \(error.localizedDescription)")
            }
        }
    }
    
    private func disableLockScreenAccess() {
        UIApplication.shared.isIdleTimerDisabled = false
    }
}

关键说明

  • Android端:当用户从SecondScreen返回MyHomePage时,dispose方法会自动调用关闭权限,恢复正常锁屏状态。
  • iOS端:通过isIdleTimerDisabled保持屏幕唤醒,静默通知用于触发锁屏状态下的屏幕亮起。
  • 整个方案基于Flutter单Activity架构,无需新增页面载体,仅在目标页面动态切换权限,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:35:01