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

React Native技术问询:如何区分后台触发方式及获取锁屏时间

区分手动切换后台与锁屏导致的后台状态

我之前帮不少开发者解决过类似的问题,其实在React Native里是可以区分这两种后台触发场景的,不过需要结合原生平台的特性或者一些成熟的第三方库来实现,下面给你详细拆解方案:

核心思路

React Native自带的AppState API只能告诉你应用进入了后台状态,但没法区分触发原因。要实现区分,关键是把原生平台的锁屏/解锁事件监听,和AppState的状态变化做关联——当应用进入后台时,如果之前先触发了锁屏事件,那就是锁屏导致的后台;反之则是手动切换。

具体实现方案

1. 用第三方库快速实现(推荐)

有几个成熟的库已经封装了锁屏监听功能,不用自己写原生代码,上手很快:

  • react-native-screen-manager:支持监听屏幕锁屏/解锁事件,搭配AppState就能轻松判断后台触发原因
    示例代码:
    import { AppState } from 'react-native';
    import ScreenManager from 'react-native-screen-manager';
    
    let isScreenLocked = false;
    
    // 监听锁屏/解锁事件
    ScreenManager.addEventListener('screenDidLock', () => {
      isScreenLocked = true;
    });
    
    ScreenManager.addEventListener('screenDidUnlock', () => {
      isScreenLocked = false;
    });
    
    // 监听应用状态变化
    AppState.addEventListener('change', (nextAppState) => {
      if (nextAppState === 'background') {
        if (isScreenLocked) {
          console.log('应用因锁屏进入后台');
        } else {
          console.log('应用被手动切换至后台');
        }
      }
    });
    
  • react-native-device-events:功能类似,也能监听屏幕状态变化,用法和上面的示例差不多。

2. 自定义原生模块(适合高度定制需求)

如果不想依赖第三方库,可以自己写原生模块来监听锁屏事件,再通过桥接把事件传递给React Native:

iOS端

在原生代码中监听系统的锁屏通知,再把事件抛给RN:

#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

@interface ScreenLockEmitter : RCTEventEmitter <RCTBridgeModule>
@end

@implementation ScreenLockEmitter

RCT_EXPORT_MODULE();

- (NSArray<NSString *> *)supportedEvents {
  return @[@"screenLocked", @"screenUnlocked"];
}

- (void)startObserving {
  // 监听锁屏/解锁通知
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(onScreenLocked)
                                               name:UIApplicationProtectedDataWillBecomeUnavailableNotification
                                             object:nil];
  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(onScreenUnlocked)
                                               name:UIApplicationProtectedDataDidBecomeAvailableNotification
                                             object:nil];
}

- (void)stopObserving {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)onScreenLocked {
  [self sendEventWithName:@"screenLocked" body:nil];
}

- (void)onScreenUnlocked {
  [self sendEventWithName:@"screenUnlocked" body:nil];
}

@end

之后在RN中通过NativeEventEmitter监听这些事件,再结合AppState判断即可。

Android端

在原生代码中注册广播接收器,监听屏幕锁屏/解锁广播:

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.modules.core.DeviceEventManagerModule;

public class ScreenLockModule extends ReactContextBaseJavaModule {
    private BroadcastReceiver screenLockReceiver;

    public ScreenLockModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "ScreenLockModule";
    }

    @Override
    public void initialize() {
        super.initialize();
        screenLockReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
                    sendEvent("screenLocked");
                } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
                    sendEvent("screenUnlocked");
                }
            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        getReactApplicationContext().registerReceiver(screenLockReceiver, filter);
    }

    @Override
    public void onCatalystInstanceDestroy() {
        super.onCatalystInstanceDestroy();
        getReactApplicationContext().unregisterReceiver(screenLockReceiver);
    }

    private void sendEvent(String eventName) {
        getReactApplicationContext()
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, null);
    }
}

同样,在RN中监听原生事件后,和AppState联动判断后台触发原因。

获取设备锁屏时间

要获取锁屏时间也需要结合原生能力:

  • 实时锁屏时间:在监听锁屏事件的同时,记录当前时间戳(RN端用Date.now(),或者原生端获取系统时间后传递给RN)。
  • 历史锁屏时间:iOS端受系统权限限制,很难获取历史记录;Android端可以通过UsageStatsManager获取,但需要申请PACKAGE_USAGE_STATS权限,且只能获取最近一段时间的记录。
总结

总的来说,通过原生锁屏事件监听 + React Native AppState的组合,完全可以区分手动切后台和锁屏导致的后台状态;获取锁屏时间也能通过第三方库或自定义原生模块实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:12:09