React Native中如何检测手机屏幕的开启/关闭状态?
准确判断移动设备屏幕状态的解决方案
针对你开发专注应用时遇到的「AppState无法区分应用切换和屏幕关闭」的问题,以下是分平台的原生实现方案(React Native无直接内置API,需通过原生模块扩展):
iOS 端实现
iOS可通过监听系统通知结合保护数据状态来区分屏幕锁定与应用切换:
- 注册监听
UIApplicationDidEnterBackgroundNotification和UIApplicationWillEnterForegroundNotification - 当应用进入后台时,检查
UIApplication.shared.isProtectedDataAvailable:- 返回
false:说明设备屏幕已锁定(关闭) - 返回
true:说明用户切换到了其他应用
- 返回
- 将状态通过原生模块桥接给React Native JS层,可导出查询方法或发送事件通知。
示例原生代码片段(Objective-C):
#import <React/RCTBridgeModule.h> #import <React/RCTEventEmitter.h> @interface ScreenStateManager : RCTEventEmitter <RCTBridgeModule> @end @implementation ScreenStateManager RCT_EXPORT_MODULE(); - (NSArray<NSString *> *)supportedEvents { return @[@"screenLocked", @"screenUnlocked"]; } - (void)startObserving { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; } - (void)stopObserving { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)onAppEnterBackground:(NSNotification *)notification { BOOL isLocked = ![[UIApplication sharedApplication] isProtectedDataAvailable]; if (isLocked) { [self sendEventWithName:@"screenLocked" body:nil]; } } - (void)onAppEnterForeground:(NSNotification *)notification { [self sendEventWithName:@"screenUnlocked" body:nil]; } RCT_EXPORT_METHOD(getCurrentScreenLockedStatus:(RCTResponseSenderBlock)callback) { BOOL isLocked = ![[UIApplication sharedApplication] isProtectedDataAvailable]; callback(@[@(isLocked)]); } @end
Android 端实现
Android通过广播接收器监听屏幕开关状态,结合AppState判断场景:
- 创建广播接收器,监听
Intent.ACTION_SCREEN_ON和Intent.ACTION_SCREEN_OFF系统广播 - 收到广播时,向React Native JS层发送对应状态事件(
screenOn/screenOff) - 在JS层结合AppState的
background事件:当AppState变为background时,若此前收到过screenOff事件则为屏幕关闭,否则为应用切换。
示例原生代码片段(Kotlin):
import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.modules.core.DeviceEventManagerModule class ScreenStateModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { private val screenReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { Intent.ACTION_SCREEN_ON -> sendEvent("screenOn") Intent.ACTION_SCREEN_OFF -> sendEvent("screenOff") } } } override fun getName(): String = "ScreenStateModule" override fun initialize() { super.initialize() val filter = IntentFilter().apply { addAction(Intent.ACTION_SCREEN_ON) addAction(Intent.ACTION_SCREEN_OFF) } reactApplicationContext.registerReceiver(screenReceiver, filter) } override fun onCatalystInstanceDestroy() { super.onCatalystInstanceDestroy() reactApplicationContext.unregisterReceiver(screenReceiver) } private fun sendEvent(eventName: String) { reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(eventName, null) } @ReactMethod fun getCurrentScreenState(callback: (Boolean) -> Unit) { val powerManager = reactApplicationContext.getSystemService(Context.POWER_SERVICE) as android.os.PowerManager callback(powerManager.isInteractive) } }
React Native JS 层整合
在JS层同时监听AppState和屏幕状态事件,实现逻辑判断:
import { AppState, NativeEventEmitter, NativeModules } from 'react-native'; const { ScreenStateModule } = NativeModules; const screenStateEmitter = new NativeEventEmitter(ScreenStateModule); let isScreenOff = false; // 监听屏幕状态 screenStateEmitter.addListener('screenLocked', () => { isScreenOff = true; }); screenStateEmitter.addListener('screenUnlocked', () => { isScreenOff = false; }); screenStateEmitter.addListener('screenOn', () => { isScreenOff = false; }); screenStateEmitter.addListener('screenOff', () => { isScreenOff = true; }); // 监听AppState变化 AppState.addEventListener('change', (nextAppState) => { if (nextAppState === 'background') { if (isScreenOff) { // 处理屏幕关闭的情况,不判定为违规 console.log('屏幕已关闭,允许'); } else { // 处理切换到其他应用的情况,判定为违规 console.log('切换到其他应用,触发专注提醒'); } } });
内容的提问来源于stack exchange,提问作者Hitul Nayakpara
相关产品推荐
相关产品推荐

