Expo ScreenCapture
一个库,可让你保护应用中的屏幕不被捕获或记录。
expo-screen-capture 允许你保护应用中的屏幕不被截屏或录制,并在应用处于前台时被通知是否有人截取了屏幕。你可能想要防止屏幕捕获的两个最常见原因是:
- 如果屏幕显示敏感信息(密码、信用卡数据等)
- 你正在显示你不希望被记录和共享的付费内容
这在 Android 上尤其重要,因为 android.media.projection API 允许第三方应用执行屏幕捕捉或屏幕共享(即使应用在后台)。
🌐 This is especially important on Android since the android.media.projection API allows third-party apps to perform screen capture or screen sharing (even if the app is in the background).
在 Android 上,屏幕捕获回调仅在 Android 14 及以上版本无需额外权限即可工作。在 Android 14+ 上,你无需请求或检查用于阻止屏幕捕获或使用回调的权限。
🌐 On Android, the screen capture callback works without additional permissions only for Android 14+. You don't need to request or check permissions for blocking screen capture or using the callback on Android 14+.
如果你想在 Android 13 或更低版本上使用屏幕捕获回调,你需要在 AndroidManifest.xml 文件中添加 READ_MEDIA_IMAGES 权限。你可以在应用配置中使用 android.permissions 键。更多信息请参阅 Android 权限。
🌐 If you want to use the screen capture callback on Android 13 or lower, you need to add the READ_MEDIA_IMAGES permission to your AndroidManifest.xml file. You can use the android.permissions key in your app config. See Android permissions for more information.
警告
READ_MEDIA_IMAGES权限仅可添加到需要广泛访问照片的应用中。详情请参阅 Google Play 关于照片和视频权限的政策。
重要 测试屏幕截图功能:在 Android 模拟器上,在单独的终端中运行
adb shell input keyevent 120以触发截图。在 iOS 模拟器上,可以通过菜单栏选择 设备 > 触发屏幕截图 来触发截图。
安装
🌐 Installation
- npx expo install expo-screen-captureIf you are installing this in an existing React Native app, make sure to install expo in your project.
用法
🌐 Usage
例子:钩子
🌐 Example: hook
import { usePreventScreenCapture } from 'expo-screen-capture'; import { Text, View } from 'react-native'; export default function ScreenCaptureExample() { usePreventScreenCapture(); return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>As long as this component is mounted, this screen is unrecordable!</Text> </View> ); }
示例:强制阻止屏幕捕捉
🌐 Example: Blocking screen capture imperatively
import * as ScreenCapture from 'expo-screen-capture'; import { useEffect } from 'react'; import { Button, StyleSheet, View } from 'react-native'; export default function ScreenCaptureExample() { const activate = async () => { await ScreenCapture.preventScreenCaptureAsync(); }; const deactivate = async () => { await ScreenCapture.allowScreenCaptureAsync(); }; return ( <View style={styles.container}> <Button title="激活" onPress={activate} /> <Button title="停用" onPress={deactivate} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, });
示例:屏幕捕获回调
🌐 Example: Callback for screen capture
import * as ScreenCapture from 'expo-screen-capture'; import { useEffect } from 'react'; import { Button, StyleSheet, View } from 'react-native'; export default function useScreenCaptureCallback() { // Only use this if you add the READ_MEDIA_IMAGES permission to your AndroidManifest.xml const hasPermissions = async () => { const { status } = await ScreenCapture.requestPermissionsAsync(); return status === 'granted'; }; useEffect(() => { let subscription; const addListenerAsync = async () => { if (await hasPermissions()) { subscription = ScreenCapture.addScreenshotListener(() => { alert('Thanks for screenshotting my beautiful app 😊'); }); } else { console.error('Permissions needed to subscribe to screenshot events are missing!'); } }; addListenerAsync(); return () => { subscription?.remove(); }; }, []); }
应用接口
🌐 API
import * as ScreenCapture from 'expo-screen-capture';
Hooks
| Parameter | Type |
|---|---|
| options(optional) | PermissionHookOptions<object> |
Check or request permissions necessary for detecting when a screenshot is taken.
This uses both requestPermissionsAsync and getPermissionsAsync to interact with the permissions.
[null | PermissionResponse, RequestPermissionMethod<PermissionResponse>, GetPermissionMethod<PermissionResponse>]Example
const [status, requestPermission] = ScreenCapture.usePermissions();
| Parameter | Type | Description |
|---|---|---|
| key(optional) | string | If provided, this will prevent multiple instances of this hook or the
Default: 'default' |
A React hook to prevent screen capturing for as long as the owner component is mounted.
void| Parameter | Type | Description |
|---|---|---|
| listener | () => void | A function that will be called whenever a screenshot is detected. This hook automatically starts listening when the component mounts, and stops listening when the component unmounts. |
A React hook that listens for screenshots taken while the component is mounted.
voidMethods
| Parameter | Type | Description |
|---|---|---|
| key(optional) | string | This will prevent multiple instances of the Default: 'default' |
Re-allows the user to screen record or screenshot your app. If you haven't called
preventScreenCapture() yet, this method does nothing.
Promise<void>Disables the privacy protection overlay that was previously enabled with enableAppSwitcherProtectionAsync.
Promise<void>| Parameter | Type | Description |
|---|---|---|
| blurIntensity(optional) | number | The intensity of the blur effect, from 0.0 (no blur) to 1.0 (maximum blur). Default is 0.5. Default: 0.5 |
Enables a privacy protection blur overlay that hides sensitive content when the app is not in focus. The overlay applies a customizable blur effect when the app is in the app switcher, background, or during interruptions (calls, Siri, Control Center, etc.), and automatically removes it when the app becomes active again.
This provides visual privacy protection by preventing sensitive app content from being visible in:
- App switcher previews
- Background app snapshots
- Screenshots taken during inactive states
For Android, app switcher protection is automatically provided by preventScreenCaptureAsync()
using the FLAG_SECURE window flag, which shows a blank screen in the recent apps preview.
Promise<void>Checks user's permissions for detecting when a screenshot is taken.
Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a
grantedpermission response.
Promise<PermissionResponse>A promise that resolves to a PermissionResponse object.
Returns whether the Screen Capture API is available on the current device.
Promise<boolean>A promise that resolves to a boolean indicating whether the Screen Capture API is available on the current
device.
| Parameter | Type | Description |
|---|---|---|
| key(optional) | string | Optional. If provided, this will help prevent multiple instances of the Default: 'default' |
Prevents screenshots and screen recordings until allowScreenCaptureAsync is called or the app is restarted. If you are
already preventing screen capture, this method does nothing (unless you pass a new and unique key).
On iOS, this prevents screen recordings and screenshots, and is only available on iOS 11+ (recordings) and iOS 13+ (screenshots). On older iOS versions, this method does nothing.
Promise<void>Asks the user to grant permissions necessary for detecting when a screenshot is taken.
Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a
grantedpermission response.
Promise<PermissionResponse>A promise that resolves to a PermissionResponse object.
Event Subscriptions
| Parameter | Type | Description |
|---|---|---|
| listener | () => void | The function that will be executed when the user takes a screenshot. This function accepts no arguments. |
Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.
Permission requirements for this method depend on your device’s Android version:
- Before Android 13: Requires
READ_EXTERNAL_STORAGE. - Android 13: Switches to
READ_MEDIA_IMAGES. - Post-Android 13: No additional permissions required.
You can request the appropriate permissions by using
MediaLibrary.requestPermissionsAsync().
EventSubscriptionA Subscription object that you can use to unregister the listener, either by calling
remove() or passing it to removeScreenshotListener.
| Parameter | Type | Description |
|---|---|---|
| subscription | EventSubscription | Subscription returned by |
Removes the subscription you provide, so that you are no longer listening for screenshots.
You can also call remove() on that Subscription object.
voidExample
let mySubscription = addScreenshotListener(() => { console.log("You took a screenshot!"); }); ... mySubscription.remove(); // OR removeScreenshotListener(mySubscription);
| Parameter | Type | Description |
|---|---|---|
| listener | () => void | A function that will be called whenever a screenshot is detected. This hook automatically starts listening when the component mounts, and stops listening when the component unmounts. |
A React hook that listens for screenshots taken while the component is mounted.
voidInterfaces
A subscription object that allows to conveniently remove an event listener from the emitter.
Types
Literal Type: union
Acceptable values are: PermissionHookBehavior | Options
An object obtained by permissions get and request functions.
| Property | Type | Description |
|---|---|---|
| canAskAgain | boolean | Indicates if user can be asked again for specific permission. If not, one should be directed to the Settings app in order to enable/disable the permission. |
| expires | PermissionExpiration | Determines time when the permission expires. |
| granted | boolean | A convenience boolean that indicates if the permission is granted. |
| status | PermissionStatus | Determines the status of the permission. |