深入 Android 源码:react-native-keep-awake 如何用 FLAG_KEEP_SCREEN_ON 实现屏幕常亮(完整指南)
2026/8/25 10:03:13 网站建设 项目流程

深入 Android 源码:react-native-keep-awake 如何用 FLAG_KEEP_SCREEN_ON 实现屏幕常亮(完整指南)

【免费下载链接】react-native-keep-awakeKeep the screen from going to sleep. iOS and Android.项目地址: https://gitcode.com/gh_mirrors/re/react-native-keep-awake

react-native-keep-awake是一个轻量级的 React Native 屏幕常亮组件,它通过 Android 系统的FLAG_KEEP_SCREEN_ON窗口标志位,防止应用在前台时屏幕自动熄灭。这篇文章带你深入源码,看懂它从 JS 层到 Android 原生的完整实现链路,适合想理解 React Native 桥接机制的初学者 📱

一、为什么需要"屏幕常亮"?

在实际开发中,有一类场景用户会长时间盯着屏幕但不频繁触摸:

  • 🗺️ 导航应用:开车导航时,屏幕熄灭等于"路痴模式"
  • 🎬 视频播放:播放器界面不希望系统打断观看
  • 🏭 工业/展示终端:设备常开常显,无人值守

Android 系统默认会根据"用户空闲时长"自动熄屏以省电。要突破这个限制,最正统的方式就是设置窗口标志位——这正是 react-native-keep-awake 的核心。

二、整体架构:一个 JS 文件 + 一个 Java 文件

这个库的代码结构极其精简,全部核心逻辑只有两个文件:

层级文件路径职责
JS 层index.js封装 React 组件,桥接到原生模块
Android 层android/src/main/java/com/corbt/keepawake/KCKeepAwake.java调用系统 API 设置屏幕常亮
Android 注册层android/src/main/java/com/corbt/keepawake/KCKeepAwakePackage.java向 React Native 注册原生模块
iOS 层ios/KCKeepAwake.m对应 iOS 端的常亮实现

整个项目就是一个"最小可运行的原生模块"范例,非常适合学习 React Native 混合开发的套路。

三、JS 层:index.js 是怎么调用原生的?

index.js里定义了一个KeepAwake组件,它有两种使用方式:

// 方式一:作为组件渲染 <KeepAwake /> // 方式二:显式调用静态方法 KeepAwake.activate(); // 屏幕常亮 KeepAwake.deactivate(); // 恢复自动熄屏

关键源码是这样的:

static activate() { NativeModules.KCKeepAwake.activate(); }

这里用到的NativeModules是 React Native 内置的桥接对象。它会把 JS 端对activate()的调用,跨语言转发到 Android 端同名的@ReactMethod方法上。

还有一个巧妙的引用计数设计:

componentDidMount() { mounted++; KeepAwake.activate(); } componentWillUnmount() { mounted--; if (!mounted) { KeepAwake.deactivate(); } }

也就是说:页面上渲染了几个<KeepAwake />mounted就加几;只有当最后一个组件卸载时,才会真正调用deactivate()关闭常亮。这样多个页面组件共用时不会互相"抢开关",是个很实用的细节 💡

四、核心源码逐行解读:FLAG_KEEP_SCREEN_ON 登场

现在进入主角——KCKeepAwake.javaactivate()方法:

@ReactMethod public void activate() { final Activity activity = getCurrentActivity(); if (activity != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } }

这 10 行代码里藏着4 个 Android 开发的关键知识点

1. 为什么要runOnUiThread

@ReactMethod方法运行在 React Native 的Native 模块线程,而不是 UI 主线程。而 Android 的Window对象只能在主线程上操作,直接调用会抛CalledFromWrongThreadException。所以必须用runOnUiThread()把操作切回主线程再执行。

2. FLAG_KEEP_SCREEN_ON 到底做了什么?

WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON是 Android 系统级的窗口标志位,它告诉窗口管理器:"这个窗口可见期间,不要启动熄屏计时器"

它的作用范围是窗口级而非全局的——只影响当前 Activity 的屏幕常亮策略,不会干扰系统其他部分,是官方推荐的省电友好的方案(相比获取WAKE_LOCK权限更轻量)。

3. addFlags 与 clearFlags 是一对

deactivate()方法与之完全对称:

activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

一增一删,保证离开页面后屏幕恢复正常的熄屏行为,不给用户"偷电"。

4. 空指针防御

if (activity != null)保护了边界情况:如果 JS 调用发生在 Activity 尚未就绪时,直接静默跳过,不会崩溃。

📌 顺带一提,iOS 端ios/KCKeepAwake.m用的是[[UIApplication sharedApplication] setIdleTimerDisabled:YES],同样是官方 API,双端思路完全一致。

五、模块注册:KCKeepAwakePackage 如何接入 React Native

JS 层能找到NativeModules.KCKeepAwake,靠的是KCKeepAwakePackage.java这个注册类:

public class KCKeepAwakePackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new KCKeepAwake(reactContext)); return modules; } }

React Native 启动时会收集所有ReactPackage,并调用createNativeModules()把原生模块注册进模块表。模块名由getName()返回"KCKeepAwake",恰好与 JS 端的NativeModules.KCKeepAwake对上——名字必须一致,这是桥接能否通的关键

六、安装与快速上手

获取源码:

git clone https://gitcode.com/gh_mirrors/re/react-native-keep-awake

在 React Native 项目中使用:

npm install --save react-native-keep-awake

然后在android/settings.gradleandroid/app/build.gradle中引入模块(详见 README.md 中的 Manual install 章节,也可用react-native link自动链接)。

使用示例:

import KeepAwake from 'react-native-keep-awake'; // 播放视频时保持屏幕常亮 function PlayerScreen() { const startPlayback = () => KeepAwake.activate(); const stopPlayback = () => KeepAwake.deactivate(); // ... }

七、实用建议与版本提醒

  • ⚠️版本提醒package.json显示当前版本为 v4.0.0,README 顶部已标注该包处于**弃用(deprecated)**状态,官方推荐转向 Expo 团队维护的expo-keep-awake或社区维护的 fork@sayem314/react-native-keep-awake。新项目选型时建议优先考虑后者。
  • ⏱️用完记得关:常亮会显著增加耗电,务必在页面卸载或任务结束时调用deactivate()
  • 🧵理解线程模型:本库演示的"桥接线程 → 主线程"切换模式,是所有 React Native 原生模块的通用写法,吃透它收益很大。

八、总结

react-native-keep-awake 用不到 100 行代码,完整展示了 React Native 跨平台开发的经典链路:

JS 组件 → NativeModules 桥接 → @ReactMethod 原生方法 → 主线程执行系统 API

其中真正"干活"的只有一行:给窗口加上FLAG_KEEP_SCREEN_ON标志位。麻雀虽小,五脏俱全——如果你想深入 Android 源码或学习 React Native 原生模块开发,这个项目值得逐行读完 👏

【免费下载链接】react-native-keep-awakeKeep the screen from going to sleep. iOS and Android.项目地址: https://gitcode.com/gh_mirrors/re/react-native-keep-awake

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询