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

Flutter开发在线考试应用如何检测Home键、最近任务键避免应用自动最小化

Flutter 在线考试应用按键拦截与检测方案

注意:受安卓、iOS系统底层限制,普通应用无法阻止点击Home键、最近任务键后应用最小化的默认行为,但可以可靠检测这两个按键的点击事件,完全满足在线考试类应用的切屏判定需求。


1. Home键、最近任务键点击检测

推荐使用第三方插件flutter_home_key_listener实现跨平台的按键事件监听,无需自行编写原生桥接代码:

  • 第一步:在pubspec.yaml中添加依赖
dependencies:
  flutter:
    sdk: flutter
  flutter_home_key_listener: ^0.0.2 # 可替换为当前最新版本
  permission_handler: ^10.2.0 # 用于安卓高版本动态权限申请
  • 第二步:安卓端权限配置,在android/app/src/main/AndroidManifest.xml的manifest节点下添加如下权限:
<!-- 监听系统按键广播所需权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- 安卓12及以上版本所需权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • 第三步:页面中实现监听逻辑
import 'package:flutter/material.dart';
import 'package:flutter_home_key_listener/flutter_home_key_listener.dart';
import 'package:permission_handler/permission_handler.dart';

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

  @override
  State<ExamPage> createState() => _ExamPageState();
}

class _ExamPageState extends State<ExamPage> with HomeKeyListenerMixin {
  @override
  void initState() {
    super.initState();
    _initPermissionAndListener();
  }

  // 初始化权限与监听
  Future<void> _initPermissionAndListener() async {
    // 安卓端先申请所需权限
    if (Theme.of(context).platform == TargetPlatform.android) {
      await Permission.phone.request();
    }
    // 开启按键监听
    FlutterHomeKeyListener.startListen();
  }

  // Home键点击回调
  @override
  void onHomeKeyPress() {
    super.onHomeKeyPress();
    // 此处编写业务逻辑,例如记录切屏次数、弹出作弊预警等
    debugPrint("用户点击了Home键");
  }

  // 最近任务键点击回调
  @override
  void onRecentAppKeyPress() {
    super.onRecentAppKeyPress();
    // 此处编写业务逻辑
    debugPrint("用户点击了最近任务键");
  }

  @override
  void dispose() {
    // 销毁时移除监听,避免内存泄漏
    FlutterHomeKeyListener.stopListen();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("在线考试")),
      body: const Center(child: Text("考试进行中...")),
    );
  }
}

2. 返回键拦截实现

Flutter内置的WillPopScope组件即可直接实现返回键拦截,自定义返回逻辑:

@override
Widget build(BuildContext context) {
  return WillPopScope(
    onWillPop: () async {
      // 示例:弹出确认退出考试的弹窗
      final confirmExit = await showDialog<bool>(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text("确认退出"),
          content: const Text("退出考试后将自动提交试卷,无法继续作答"),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context, false),
              child: const Text("取消"),
            ),
            TextButton(
              onPressed: () => Navigator.pop(context, true),
              child: const Text("确认退出"),
            ),
          ],
        ),
      );
      // 返回true则执行返回逻辑,返回false则拦截返回操作
      return confirmExit ?? false;
    },
    child: Scaffold(
      appBar: AppBar(title: const Text("在线考试")),
      body: const Center(child: Text("考试进行中...")),
    ),
  );
}

3. 附加防作弊优化建议

  • 若需要减少用户切出考试页面的概率,可在检测到Home/最近任务键点击后,调用flutter_windowmanager插件将应用立刻拉回前台
  • 可添加禁止截屏、禁止分屏逻辑,安卓端可在MainActivity的onCreate方法中添加如下代码:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 禁止截屏、录屏
    window.addFlags(android.view.WindowManager.LayoutParams.FLAG_SECURE)
    // 保持屏幕常亮
    window.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:54:01