Screen capture

ScreenCapture keeps sensitive screens out of screenshots and screen recordings, and counts the screenshots the user takes, bound to expo-screen-capture.

Import
import { ScreenCapture } from '@ng-native/expo';
Inject
inject(ScreenCapture)

Preventing capture is held by a key, and stays on while any key is held: a payment screen and a passwords screen that each prevent it do not undo each other when one of them closes. The screenshot count is a signal, and the listener behind it lives as long as the app does and is removed when the app is destroyed.

Install

npx expo install expo-screen-capture
import { ScreenCapture } from '@ng-native/expo/screen-capture';

The smallest useful example

import { Component, DestroyRef, inject } from '@angular/core';
import { Text } from '@ng-native/components';
import { ScreenCapture } from '@ng-native/expo/screen-capture';

@Component({
  selector: 'app-card-details',
  imports: [Text],
  template: `
    <text>4242 4242 4242 4242</text>
    @if (capture.screenshots() > 0) {
      <text>Screenshots of this screen show your card number.</text>
    }
  `,
})
export class CardDetails {
  protected readonly capture = inject(ScreenCapture);

  constructor() {
    void this.capture.prevent('card-details');
    inject(DestroyRef).onDestroy(() => void this.capture.allow('card-details'));
  }
}

What it does

  • screenshots - a signal: how many screenshots the user has taken while the app was in front. The event carries nothing else, so a count is all there is to hold.
  • prevent(key?) - keeps the app out of screenshots and screen recordings until allow() is called with the same key, or the app is destroyed. Without a key, one shared default key is used. Keys are counted across every app the runtime mounts, so an app allowing a key leaves it held for another app that prevents it too. On Android, an activity that comes to the front while a key is held is kept out of capture again.
  • allow(key?) - releases the key. Capture is allowed again once no key is held.
  • available() - whether the platform can prevent capture.
  • protectAppSwitcher(blurIntensity?) and unprotectAppSwitcher() - hide the app's content in the app switcher and leave screenshots allowed. iOS: blurs the app while it is not in focus - in the app switcher, in the background, during interruptions - by an intensity from 0 to 1, half by default. Android 13 and later: leaves the app's snapshot out of recent apps, including after the activity is recreated, through this package's native half, so it needs a development build; the intensity is not used. Earlier Android, and Expo Go on Android, do nothing: prevent() hides the app in recent apps there, and blocks screenshots too.
  • permission - a Permission for screenshot detection. Android 13 and earlier need it, since detection reads the photo library; later Android needs none, and iOS always answers granted.

Without the module

On iOS and Android, a missing expo-screen-capture - never installed, or installed without the app being rebuilt since - leaves the service made, so injecting it does not throw. A call, or a read of a value only the module knows, throws a MissingModuleError. Its message names the module and the commands that fix it; see Using a module.

On the web, and in a test that provides no fake, screenshots stays at 0, available() resolves to false, the permission is refused, and every other method resolves without doing anything.

Reference

ScreenCaptureservice@ng-native/expo
import { ScreenCapture } from '@ng-native/expo';

Methods

available(): Promise<boolean>

Whether the platform can prevent capture.

prevent(key?: string): Promise<void>

Keeps the app out of screenshots and screen recordings until allow() is called with the same key, or the app goes. Omitting the key uses one shared default key.

allow(key?: string): Promise<void>

Releases the key; capture is allowed again once no key is held.

protectAppSwitcher(blurIntensity?: number): Promise<void>

Hides the app's content in the app switcher, and leaves screenshots allowed. iOS: blurs the app while it is not in focus - in the app switcher, in the background, and during interruptions - by blurIntensity from 0 to 1, half by default. Android 13 and later: leaves the app's snapshot out of recent apps, with this package's native half; blurIntensity is not used. Earlier Android, and a build without the native half such as Expo Go, do nothing.

unprotectAppSwitcher(): Promise<void>

Shows the app's content in the app switcher again.

Angular components as native iOS and Android views, built and shipped with Expo.

An alpha. MIT licensed. Sponsor its development.

An independent project, not affiliated with or endorsed by Google, the Angular team or Expo. Angular is a trademark of Google LLC.