expo-screen-capture 7.2.0 → 7.3.0-canary-20250811-5c940c0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +6 -9
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/AndroidManifest.xml +1 -0
  4. package/build/ScreenCapture.d.ts +15 -2
  5. package/build/ScreenCapture.d.ts.map +1 -1
  6. package/build/ScreenCapture.js +23 -2
  7. package/build/ScreenCapture.js.map +1 -1
  8. package/expo-module.config.json +1 -1
  9. package/ios/ExpoScreenCapture.podspec +1 -1
  10. package/ios/ScreenCaptureModule.swift +15 -20
  11. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar +0 -0
  12. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar.md5 +1 -0
  13. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar.sha1 +1 -0
  14. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar.sha256 +1 -0
  15. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar.sha512 +1 -0
  16. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0.module → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.module} +19 -19
  17. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.module.md5 +1 -0
  18. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.module.sha1 +1 -0
  19. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.module.sha256 +1 -0
  20. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.module.sha512 +1 -0
  21. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0.pom → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.pom} +2 -2
  22. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.pom.md5 +1 -0
  23. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.pom.sha1 +1 -0
  24. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.pom.sha256 +1 -0
  25. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.pom.sha512 +1 -0
  26. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/maven-metadata.xml +4 -4
  27. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/maven-metadata.xml.md5 +1 -1
  28. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/maven-metadata.xml.sha1 +1 -1
  29. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/maven-metadata.xml.sha256 +1 -1
  30. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/maven-metadata.xml.sha512 +1 -1
  31. package/package.json +4 -5
  32. package/src/ScreenCapture.ts +25 -2
  33. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.aar +0 -0
  34. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.aar.md5 +0 -1
  35. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.aar.sha1 +0 -1
  36. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.aar.sha256 +0 -1
  37. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.aar.sha512 +0 -1
  38. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.module.md5 +0 -1
  39. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.module.sha1 +0 -1
  40. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.module.sha256 +0 -1
  41. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.module.sha512 +0 -1
  42. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.pom.md5 +0 -1
  43. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.pom.sha1 +0 -1
  44. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.pom.sha256 +0 -1
  45. package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/7.2.0/expo.modules.screencapture-7.2.0.pom.sha512 +0 -1
  46. /package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0-sources.jar → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar} +0 -0
  47. /package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0-sources.jar.md5 → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar.md5} +0 -0
  48. /package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0-sources.jar.sha1 → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar.sha1} +0 -0
  49. /package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0-sources.jar.sha256 → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar.sha256} +0 -0
  50. /package/local-maven-repo/host/exp/exponent/expo.modules.screencapture/{7.2.0/expo.modules.screencapture-7.2.0-sources.jar.sha512 → 7.3.0-canary-20250811-5c940c0/expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar.sha512} +0 -0
package/CHANGELOG.md CHANGED
@@ -6,23 +6,20 @@
6
6
 
7
7
  ### 🎉 New features
8
8
 
9
- ### 🐛 Bug fixes
10
-
11
- ### 💡 Others
12
-
13
- ## 7.2.0 — 2025-07-23
14
-
15
- ### 🎉 New features
16
-
17
9
  - Implemented `useScreenshotListener` hook. ([#37411](https://github.com/expo/expo/pull/37411) by [@hryhoriiK97](https://github.com/hryhoriiK97))
18
10
  - Implemented screenshot prevention on iOS. ([#37874](https://github.com/expo/expo/pull/37874) by [@hryhoriiK97](https://github.com/hryhoriiK97))
19
11
  - Implement App Switcher protection on iOS. ([#38192](https://github.com/expo/expo/pull/38192) by [@hryhoriiK97](https://github.com/hryhoriiK97))
20
12
 
13
+ ### 🐛 Bug fixes
14
+
15
+ - [Android] Fix permissions on Android 13.
16
+ - [iOS] Fix issue with header flickering on screenshot prevention. ([#38384](https://github.com/expo/expo/pull/38384) by [@hryhoriiK97](https://github.com/hryhoriiK97))
17
+
21
18
  ### 💡 Others
22
19
 
23
20
  - [iOS] Replaced deprecated keyWindow usage. ([#38207](https://github.com/expo/expo/pull/38207) by [@hryhoriiK97](https://github.com/hryhoriiK97))
24
21
 
25
- ## 7.1.5 2025-07-01
22
+ ## 7.1.5 - 2025-07-01
26
23
 
27
24
  ### 💡 Others
28
25
 
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '7.2.0'
7
+ version = '7.3.0-canary-20250811-5c940c0'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.screencapture"
11
11
  defaultConfig {
12
12
  versionCode 7
13
- versionName '7.2.0'
13
+ versionName '7.3.0-canary-20250811-5c940c0'
14
14
  }
15
15
  }
16
16
 
@@ -1,4 +1,5 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
2
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
3
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" android:maxSdkVersion="33"/>
3
4
  <uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" android:minSdkVersion="34" />
4
5
  </manifest>
@@ -67,8 +67,12 @@ export declare function enableAppSwitcherProtectionAsync(blurIntensity?: number)
67
67
  export declare function disableAppSwitcherProtectionAsync(): Promise<void>;
68
68
  /**
69
69
  * Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.
70
- * On Android, this method requires the `READ_EXTERNAL_STORAGE` permission. You can request this
71
- * with [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
70
+ *
71
+ * Permission requirements for this method depend on your device’s Android version:
72
+ * - **Before Android 13**: Requires `READ_EXTERNAL_STORAGE`.
73
+ * - **Android 13**: Switches to `READ_MEDIA_IMAGES`.
74
+ * - **Post-Android 13**: No additional permissions required.
75
+ * You can request the appropriate permissions by using [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
72
76
  *
73
77
  * @param listener The function that will be executed when the user takes a screenshot.
74
78
  * This function accepts no arguments.
@@ -95,6 +99,15 @@ export declare function addScreenshotListener(listener: () => void): EventSubscr
95
99
  * ```
96
100
  */
97
101
  export declare function removeScreenshotListener(subscription: EventSubscription): void;
102
+ /**
103
+ * A React hook that listens for screenshots taken while the component is mounted.
104
+ *
105
+ * @param listener A function that will be called whenever a screenshot is detected.
106
+ *
107
+ * This hook automatically starts listening when the component mounts, and stops
108
+ * listening when the component unmounts.
109
+ */
110
+ export declare function useScreenshotListener(listener: () => void): void;
98
111
  /**
99
112
  * Checks user's permissions for detecting when a screenshot is taken.
100
113
  * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.
@@ -1 +1 @@
1
- {"version":3,"file":"ScreenCapture.d.ts","sourceRoot":"","sources":["../src/ScreenCapture.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAU3B;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAStF;AAGD;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAGD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAkB,GAAG,IAAI,CAQrE;AAGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gCAAgC,CAAC,aAAa,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjG;AAGD;;;;GAIG;AACH,wBAAsB,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvE;AAGD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,iBAAiB,CAE7E;AAGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,iBAAiB,QAEvE;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAKvE;AAED;;;;KAIK;AACL,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAK3E;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,4JAGzB,CAAC;AASH,OAAO,EACL,iBAAiB,IAAI,YAAY,EACjC,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,CAAC"}
1
+ {"version":3,"file":"ScreenCapture.d.ts","sourceRoot":"","sources":["../src/ScreenCapture.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAU3B;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEzD;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAStF;AAGD;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAGD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAkB,GAAG,IAAI,CAQrE;AAGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gCAAgC,CAAC,aAAa,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjG;AAGD;;;;GAIG;AACH,wBAAsB,iCAAiC,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvE;AAGD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,iBAAiB,CAE7E;AAGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,iBAAiB,QAEvE;AAGD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,IAAI,QAQzD;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAKvE;AAED;;;;KAIK;AACL,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAK3E;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,4JAGzB,CAAC;AASH,OAAO,EACL,iBAAiB,IAAI,YAAY,EACjC,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,GACtB,CAAC"}
@@ -113,8 +113,12 @@ export async function disableAppSwitcherProtectionAsync() {
113
113
  // @needsAudit
114
114
  /**
115
115
  * Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.
116
- * On Android, this method requires the `READ_EXTERNAL_STORAGE` permission. You can request this
117
- * with [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
116
+ *
117
+ * Permission requirements for this method depend on your device’s Android version:
118
+ * - **Before Android 13**: Requires `READ_EXTERNAL_STORAGE`.
119
+ * - **Android 13**: Switches to `READ_MEDIA_IMAGES`.
120
+ * - **Post-Android 13**: No additional permissions required.
121
+ * You can request the appropriate permissions by using [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
118
122
  *
119
123
  * @param listener The function that will be executed when the user takes a screenshot.
120
124
  * This function accepts no arguments.
@@ -146,6 +150,23 @@ export function addScreenshotListener(listener) {
146
150
  export function removeScreenshotListener(subscription) {
147
151
  subscription.remove();
148
152
  }
153
+ // @needsAudit
154
+ /**
155
+ * A React hook that listens for screenshots taken while the component is mounted.
156
+ *
157
+ * @param listener A function that will be called whenever a screenshot is detected.
158
+ *
159
+ * This hook automatically starts listening when the component mounts, and stops
160
+ * listening when the component unmounts.
161
+ */
162
+ export function useScreenshotListener(listener) {
163
+ useEffect(() => {
164
+ const subscription = addScreenshotListener(listener);
165
+ return () => {
166
+ removeScreenshotListener(subscription);
167
+ };
168
+ }, [listener]);
169
+ }
149
170
  /**
150
171
  * Checks user's permissions for detecting when a screenshot is taken.
151
172
  * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.
@@ -1 +1 @@
1
- {"version":3,"file":"ScreenCapture.js","sourceRoot":"","sources":["../src/ScreenCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n UnavailabilityError,\n PermissionResponse,\n PermissionStatus,\n createPermissionHook,\n PermissionHookOptions,\n EventSubscription,\n} from 'expo-modules-core';\nimport { useEffect } from 'react';\n\nimport ExpoScreenCapture from './ExpoScreenCapture';\n\nconst activeTags: Set<string> = new Set();\n\nconst onScreenshotEventName = 'onScreenshot';\n\n// @needsAudit\n/**\n * Returns whether the Screen Capture API is available on the current device.\n *\n * @returns A promise that resolves to a `boolean` indicating whether the Screen Capture API is available on the current\n * device.\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n return !!ExpoScreenCapture.preventScreenCapture && !!ExpoScreenCapture.allowScreenCapture;\n}\n\n// @needsAudit\n/**\n * Prevents screenshots and screen recordings until `allowScreenCaptureAsync` is called or the app is restarted. If you are\n * already preventing screen capture, this method does nothing (unless you pass a new and unique `key`).\n *\n * > On iOS, this prevents screen recordings and screenshots, and is only available on iOS 11+ (recordings) and iOS 13+ (screenshots). On older\n * iOS versions, this method does nothing.\n *\n * @param key Optional. If provided, this will help prevent multiple instances of the `preventScreenCaptureAsync`\n * and `allowScreenCaptureAsync` methods (and `usePreventScreenCapture` hook) from conflicting with each other.\n * When using multiple keys, you'll have to re-allow each one in order to re-enable screen capturing.\n *\n * @platform android\n * @platform ios\n */\nexport async function preventScreenCaptureAsync(key: string = 'default'): Promise<void> {\n if (!ExpoScreenCapture.preventScreenCapture) {\n throw new UnavailabilityError('ScreenCapture', 'preventScreenCaptureAsync');\n }\n\n if (!activeTags.has(key)) {\n activeTags.add(key);\n await ExpoScreenCapture.preventScreenCapture();\n }\n}\n\n// @needsAudit\n/**\n * Re-allows the user to screen record or screenshot your app. If you haven't called\n * `preventScreenCapture()` yet, this method does nothing.\n *\n * @param key This will prevent multiple instances of the `preventScreenCaptureAsync` and\n * `allowScreenCaptureAsync` methods from conflicting with each other. If provided, the value must\n * be the same as the key passed to `preventScreenCaptureAsync` in order to re-enable screen\n * capturing.\n */\nexport async function allowScreenCaptureAsync(key: string = 'default'): Promise<void> {\n if (!ExpoScreenCapture.preventScreenCapture) {\n throw new UnavailabilityError('ScreenCapture', 'allowScreenCaptureAsync');\n }\n\n activeTags.delete(key);\n if (activeTags.size === 0) {\n await ExpoScreenCapture.allowScreenCapture();\n }\n}\n\n// @needsAudit\n/**\n * A React hook to prevent screen capturing for as long as the owner component is mounted.\n *\n * @param key If provided, this will prevent multiple instances of this hook or the\n * `preventScreenCaptureAsync` and `allowScreenCaptureAsync` methods from conflicting with each other.\n * This argument is useful if you have multiple active components using the `allowScreenCaptureAsync`\n * hook.\n */\nexport function usePreventScreenCapture(key: string = 'default'): void {\n useEffect(() => {\n preventScreenCaptureAsync(key);\n\n return () => {\n allowScreenCaptureAsync(key);\n };\n }, [key]);\n}\n\n// @needsAudit\n/**\n * Enables a privacy protection blur overlay that hides sensitive content when the app is not in focus.\n * The overlay applies a customizable blur effect when the app is in the app switcher, background, or during interruptions\n * (calls, Siri, Control Center, etc.), and automatically removes it when the app becomes active again.\n *\n * This provides visual privacy protection by preventing sensitive app content from being visible in:\n * - App switcher previews\n * - Background app snapshots\n * - Screenshots taken during inactive states\n *\n * For Android, app switcher protection is automatically provided by `preventScreenCaptureAsync()`\n * using the FLAG_SECURE window flag, which shows a blank screen in the recent apps preview.\n *\n * @param blurIntensity The intensity of the blur effect, from 0.0 (no blur) to 1.0 (maximum blur). Default is 0.5.\n *\n * @platform ios\n *\n */\nexport async function enableAppSwitcherProtectionAsync(blurIntensity: number = 0.5): Promise<void> {\n if (!ExpoScreenCapture.enableAppSwitcherProtection) {\n throw new UnavailabilityError('ScreenCapture', 'enableAppSwitcherProtectionAsync');\n }\n\n await ExpoScreenCapture.enableAppSwitcherProtection(blurIntensity);\n}\n\n// @needsAudit\n/**\n * Disables the privacy protection overlay that was previously enabled with `enableAppSwitcherProtectionAsync`.\n *\n * @platform ios\n */\nexport async function disableAppSwitcherProtectionAsync(): Promise<void> {\n if (!ExpoScreenCapture.disableAppSwitcherProtection) {\n throw new UnavailabilityError('ScreenCapture', 'disableAppSwitcherProtectionAsync');\n }\n\n await ExpoScreenCapture.disableAppSwitcherProtection();\n}\n\n// @needsAudit\n/**\n * Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.\n * On Android, this method requires the `READ_EXTERNAL_STORAGE` permission. You can request this\n * with [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).\n *\n * @param listener The function that will be executed when the user takes a screenshot.\n * This function accepts no arguments.\n *\n * @return A `Subscription` object that you can use to unregister the listener, either by calling\n * `remove()` or passing it to `removeScreenshotListener`.\n */\nexport function addScreenshotListener(listener: () => void): EventSubscription {\n return ExpoScreenCapture.addListener(onScreenshotEventName, listener);\n}\n\n// @needsAudit\n/**\n * Removes the subscription you provide, so that you are no longer listening for screenshots.\n * You can also call `remove()` on that `Subscription` object.\n *\n * @param subscription Subscription returned by `addScreenshotListener`.\n *\n * @example\n * ```ts\n * let mySubscription = addScreenshotListener(() => {\n * console.log(\"You took a screenshot!\");\n * });\n * ...\n * mySubscription.remove();\n * // OR\n * removeScreenshotListener(mySubscription);\n * ```\n */\nexport function removeScreenshotListener(subscription: EventSubscription) {\n subscription.remove();\n}\n\n/**\n * Checks user's permissions for detecting when a screenshot is taken.\n * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.\n * @return A promise that resolves to a [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function getPermissionsAsync(): Promise<PermissionResponse> {\n if (ExpoScreenCapture.getPermissionsAsync) {\n return ExpoScreenCapture.getPermissionsAsync();\n }\n return defaultPermissionsResponse;\n}\n\n/**\n * Asks the user to grant permissions necessary for detecting when a screenshot is taken.\n * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.\n * @return A promise that resolves to a [`PermissionResponse`](#permissionresponse) object.\n * */\nexport async function requestPermissionsAsync(): Promise<PermissionResponse> {\n if (ExpoScreenCapture.requestPermissionsAsync) {\n return ExpoScreenCapture.requestPermissionsAsync();\n }\n return defaultPermissionsResponse;\n}\n\n/**\n * Check or request permissions necessary for detecting when a screenshot is taken.\n * This uses both [`requestPermissionsAsync`](#screencapturerequestpermissionsasync) and [`getPermissionsAsync`](#screencapturegetpermissionsasync) to interact with the permissions.\n *\n * @example\n * ```js\n * const [status, requestPermission] = ScreenCapture.usePermissions();\n * ```\n */\nexport const usePermissions = createPermissionHook({\n getMethod: getPermissionsAsync,\n requestMethod: requestPermissionsAsync,\n});\n\nconst defaultPermissionsResponse: PermissionResponse = {\n granted: true,\n expires: 'never',\n canAskAgain: true,\n status: PermissionStatus.GRANTED,\n};\n\nexport {\n EventSubscription as Subscription,\n PermissionResponse,\n PermissionStatus,\n PermissionHookOptions,\n};\n"]}
1
+ {"version":3,"file":"ScreenCapture.js","sourceRoot":"","sources":["../src/ScreenCapture.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n UnavailabilityError,\n PermissionResponse,\n PermissionStatus,\n createPermissionHook,\n PermissionHookOptions,\n EventSubscription,\n} from 'expo-modules-core';\nimport { useEffect } from 'react';\n\nimport ExpoScreenCapture from './ExpoScreenCapture';\n\nconst activeTags: Set<string> = new Set();\n\nconst onScreenshotEventName = 'onScreenshot';\n\n// @needsAudit\n/**\n * Returns whether the Screen Capture API is available on the current device.\n *\n * @returns A promise that resolves to a `boolean` indicating whether the Screen Capture API is available on the current\n * device.\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n return !!ExpoScreenCapture.preventScreenCapture && !!ExpoScreenCapture.allowScreenCapture;\n}\n\n// @needsAudit\n/**\n * Prevents screenshots and screen recordings until `allowScreenCaptureAsync` is called or the app is restarted. If you are\n * already preventing screen capture, this method does nothing (unless you pass a new and unique `key`).\n *\n * > On iOS, this prevents screen recordings and screenshots, and is only available on iOS 11+ (recordings) and iOS 13+ (screenshots). On older\n * iOS versions, this method does nothing.\n *\n * @param key Optional. If provided, this will help prevent multiple instances of the `preventScreenCaptureAsync`\n * and `allowScreenCaptureAsync` methods (and `usePreventScreenCapture` hook) from conflicting with each other.\n * When using multiple keys, you'll have to re-allow each one in order to re-enable screen capturing.\n *\n * @platform android\n * @platform ios\n */\nexport async function preventScreenCaptureAsync(key: string = 'default'): Promise<void> {\n if (!ExpoScreenCapture.preventScreenCapture) {\n throw new UnavailabilityError('ScreenCapture', 'preventScreenCaptureAsync');\n }\n\n if (!activeTags.has(key)) {\n activeTags.add(key);\n await ExpoScreenCapture.preventScreenCapture();\n }\n}\n\n// @needsAudit\n/**\n * Re-allows the user to screen record or screenshot your app. If you haven't called\n * `preventScreenCapture()` yet, this method does nothing.\n *\n * @param key This will prevent multiple instances of the `preventScreenCaptureAsync` and\n * `allowScreenCaptureAsync` methods from conflicting with each other. If provided, the value must\n * be the same as the key passed to `preventScreenCaptureAsync` in order to re-enable screen\n * capturing.\n */\nexport async function allowScreenCaptureAsync(key: string = 'default'): Promise<void> {\n if (!ExpoScreenCapture.preventScreenCapture) {\n throw new UnavailabilityError('ScreenCapture', 'allowScreenCaptureAsync');\n }\n\n activeTags.delete(key);\n if (activeTags.size === 0) {\n await ExpoScreenCapture.allowScreenCapture();\n }\n}\n\n// @needsAudit\n/**\n * A React hook to prevent screen capturing for as long as the owner component is mounted.\n *\n * @param key If provided, this will prevent multiple instances of this hook or the\n * `preventScreenCaptureAsync` and `allowScreenCaptureAsync` methods from conflicting with each other.\n * This argument is useful if you have multiple active components using the `allowScreenCaptureAsync`\n * hook.\n */\nexport function usePreventScreenCapture(key: string = 'default'): void {\n useEffect(() => {\n preventScreenCaptureAsync(key);\n\n return () => {\n allowScreenCaptureAsync(key);\n };\n }, [key]);\n}\n\n// @needsAudit\n/**\n * Enables a privacy protection blur overlay that hides sensitive content when the app is not in focus.\n * The overlay applies a customizable blur effect when the app is in the app switcher, background, or during interruptions\n * (calls, Siri, Control Center, etc.), and automatically removes it when the app becomes active again.\n *\n * This provides visual privacy protection by preventing sensitive app content from being visible in:\n * - App switcher previews\n * - Background app snapshots\n * - Screenshots taken during inactive states\n *\n * For Android, app switcher protection is automatically provided by `preventScreenCaptureAsync()`\n * using the FLAG_SECURE window flag, which shows a blank screen in the recent apps preview.\n *\n * @param blurIntensity The intensity of the blur effect, from 0.0 (no blur) to 1.0 (maximum blur). Default is 0.5.\n *\n * @platform ios\n *\n */\nexport async function enableAppSwitcherProtectionAsync(blurIntensity: number = 0.5): Promise<void> {\n if (!ExpoScreenCapture.enableAppSwitcherProtection) {\n throw new UnavailabilityError('ScreenCapture', 'enableAppSwitcherProtectionAsync');\n }\n\n await ExpoScreenCapture.enableAppSwitcherProtection(blurIntensity);\n}\n\n// @needsAudit\n/**\n * Disables the privacy protection overlay that was previously enabled with `enableAppSwitcherProtectionAsync`.\n *\n * @platform ios\n */\nexport async function disableAppSwitcherProtectionAsync(): Promise<void> {\n if (!ExpoScreenCapture.disableAppSwitcherProtection) {\n throw new UnavailabilityError('ScreenCapture', 'disableAppSwitcherProtectionAsync');\n }\n\n await ExpoScreenCapture.disableAppSwitcherProtection();\n}\n\n// @needsAudit\n/**\n * Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.\n *\n * Permission requirements for this method depend on your device’s Android version:\n * - **Before Android 13**: Requires `READ_EXTERNAL_STORAGE`.\n * - **Android 13**: Switches to `READ_MEDIA_IMAGES`.\n * - **Post-Android 13**: No additional permissions required.\n * You can request the appropriate permissions by using [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).\n *\n * @param listener The function that will be executed when the user takes a screenshot.\n * This function accepts no arguments.\n *\n * @return A `Subscription` object that you can use to unregister the listener, either by calling\n * `remove()` or passing it to `removeScreenshotListener`.\n */\nexport function addScreenshotListener(listener: () => void): EventSubscription {\n return ExpoScreenCapture.addListener(onScreenshotEventName, listener);\n}\n\n// @needsAudit\n/**\n * Removes the subscription you provide, so that you are no longer listening for screenshots.\n * You can also call `remove()` on that `Subscription` object.\n *\n * @param subscription Subscription returned by `addScreenshotListener`.\n *\n * @example\n * ```ts\n * let mySubscription = addScreenshotListener(() => {\n * console.log(\"You took a screenshot!\");\n * });\n * ...\n * mySubscription.remove();\n * // OR\n * removeScreenshotListener(mySubscription);\n * ```\n */\nexport function removeScreenshotListener(subscription: EventSubscription) {\n subscription.remove();\n}\n\n// @needsAudit\n/**\n * A React hook that listens for screenshots taken while the component is mounted.\n *\n * @param listener A function that will be called whenever a screenshot is detected.\n *\n * This hook automatically starts listening when the component mounts, and stops\n * listening when the component unmounts.\n */\nexport function useScreenshotListener(listener: () => void) {\n useEffect(() => {\n const subscription = addScreenshotListener(listener);\n\n return () => {\n removeScreenshotListener(subscription);\n };\n }, [listener]);\n}\n\n/**\n * Checks user's permissions for detecting when a screenshot is taken.\n * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.\n * @return A promise that resolves to a [`PermissionResponse`](#permissionresponse) object.\n */\nexport async function getPermissionsAsync(): Promise<PermissionResponse> {\n if (ExpoScreenCapture.getPermissionsAsync) {\n return ExpoScreenCapture.getPermissionsAsync();\n }\n return defaultPermissionsResponse;\n}\n\n/**\n * Asks the user to grant permissions necessary for detecting when a screenshot is taken.\n * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.\n * @return A promise that resolves to a [`PermissionResponse`](#permissionresponse) object.\n * */\nexport async function requestPermissionsAsync(): Promise<PermissionResponse> {\n if (ExpoScreenCapture.requestPermissionsAsync) {\n return ExpoScreenCapture.requestPermissionsAsync();\n }\n return defaultPermissionsResponse;\n}\n\n/**\n * Check or request permissions necessary for detecting when a screenshot is taken.\n * This uses both [`requestPermissionsAsync`](#screencapturerequestpermissionsasync) and [`getPermissionsAsync`](#screencapturegetpermissionsasync) to interact with the permissions.\n *\n * @example\n * ```js\n * const [status, requestPermission] = ScreenCapture.usePermissions();\n * ```\n */\nexport const usePermissions = createPermissionHook({\n getMethod: getPermissionsAsync,\n requestMethod: requestPermissionsAsync,\n});\n\nconst defaultPermissionsResponse: PermissionResponse = {\n granted: true,\n expires: 'never',\n canAskAgain: true,\n status: PermissionStatus.GRANTED,\n};\n\nexport {\n EventSubscription as Subscription,\n PermissionResponse,\n PermissionStatus,\n PermissionHookOptions,\n};\n"]}
@@ -8,7 +8,7 @@
8
8
  "publication": {
9
9
  "groupId": "host.exp.exponent",
10
10
  "artifactId": "expo.modules.screencapture",
11
- "version": "7.2.0",
11
+ "version": "7.3.0-canary-20250811-5c940c0",
12
12
  "repository": "local-maven-repo"
13
13
  }
14
14
  }
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
13
13
  s.platforms = {
14
14
  :ios => '15.1'
15
15
  }
16
- s.swift_version = '5.4'
16
+ s.swift_version = '5.9'
17
17
  s.source = { git: 'https://github.com/expo/expo.git' }
18
18
  s.static_framework = true
19
19
 
@@ -115,43 +115,38 @@ public final class ScreenCaptureModule: Module {
115
115
  }
116
116
 
117
117
  private func preventScreenshots() {
118
- guard let keyWindow = keyWindow,
119
- let visibleView = keyWindow.subviews.first else { return }
118
+ guard let keyWindow = keyWindow else {
119
+ return
120
+ }
120
121
 
121
122
  let textField = UITextField()
122
123
  textField.isSecureTextEntry = true
123
124
  textField.isUserInteractionEnabled = false
124
- textField.backgroundColor = UIColor.black
125
+ textField.backgroundColor = UIColor.clear
126
+ textField.frame = UIScreen.main.bounds
125
127
 
126
- originalParent = visibleView.layer.superlayer
128
+ originalParent = keyWindow.layer.superlayer
127
129
 
128
- if let viewSuperlayer = visibleView.layer.superlayer {
129
- viewSuperlayer.addSublayer(textField.layer)
130
+ keyWindow.layer.superlayer?.addSublayer(textField.layer)
130
131
 
131
- if let firstTextFieldSublayer = textField.layer.sublayers?.first {
132
- visibleView.layer.removeFromSuperlayer()
133
- visibleView.layer.position = CGPoint(x: visibleView.bounds.width / 2, y: visibleView.bounds.height / 2)
134
- firstTextFieldSublayer.addSublayer(visibleView.layer)
135
- }
132
+ if let firstTextFieldSublayer = textField.layer.sublayers?.first {
133
+ keyWindow.layer.removeFromSuperlayer()
134
+ firstTextFieldSublayer.addSublayer(keyWindow.layer)
136
135
  }
137
136
 
138
137
  protectionTextField = textField
139
138
  }
140
139
 
141
140
  private func allowScreenshots() {
142
- guard let textField = protectionTextField else {
141
+ guard let textField = protectionTextField,
142
+ let window = keyWindow,
143
+ let originalParentLayer = originalParent else {
143
144
  return
144
145
  }
145
146
 
146
- if let protectedLayer = textField.layer.sublayers?.first?.sublayers?.first {
147
- protectedLayer.removeFromSuperlayer()
148
- if let parent = originalParent {
149
- parent.addSublayer(protectedLayer)
150
- }
151
- }
152
-
147
+ window.layer.removeFromSuperlayer()
148
+ originalParentLayer.addSublayer(window.layer)
153
149
  textField.layer.removeFromSuperlayer()
154
-
155
150
  protectionTextField = nil
156
151
  originalParent = nil
157
152
  }
@@ -0,0 +1 @@
1
+ 5d693f6a83cc09074f42ae55d49f7cccfc0c2e1f024e43d866c285e18f0e37648ff966eb7507567538355f6d9f1b6c7d51f6eb45456dbe191ad41f3ae896f930
@@ -3,14 +3,14 @@
3
3
  "component": {
4
4
  "group": "host.exp.exponent",
5
5
  "module": "expo.modules.screencapture",
6
- "version": "7.2.0",
6
+ "version": "7.3.0-canary-20250811-5c940c0",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
10
10
  },
11
11
  "createdBy": {
12
12
  "gradle": {
13
- "version": "8.13"
13
+ "version": "8.14"
14
14
  }
15
15
  },
16
16
  "variants": [
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.screencapture-7.2.0.aar",
28
- "url": "expo.modules.screencapture-7.2.0.aar",
29
- "size": 28229,
30
- "sha512": "e43057ceb38b0158e6866e120313f3d2f77ced9e1ac025667c2bebe36e528d537a248d4d7bff6c6db7683287ff777e14b651597b26636f7a1170825e35ea25b9",
31
- "sha256": "e530fcfe5b4c0ca8362bc07e085bfd113e6bb5f9798cde28925b64c238ce77eb",
32
- "sha1": "7ecf0a53df33e2c96fb06dd301d6a5e0824282f0",
33
- "md5": "7bd790ffca2e473cce9d80535730ba3c"
27
+ "name": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar",
28
+ "url": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar",
29
+ "size": 28245,
30
+ "sha512": "5d693f6a83cc09074f42ae55d49f7cccfc0c2e1f024e43d866c285e18f0e37648ff966eb7507567538355f6d9f1b6c7d51f6eb45456dbe191ad41f3ae896f930",
31
+ "sha256": "8a9e3dca21a096209a62e8ce26c3733e57135f9d59a41eb237636ae81c744345",
32
+ "sha1": "bff3c51739c45f8a9d1b2184ddfb30538a689344",
33
+ "md5": "3a53f7e2c485ed09380013fe5be379c8"
34
34
  }
35
35
  ]
36
36
  },
@@ -47,7 +47,7 @@
47
47
  "group": "org.jetbrains.kotlin",
48
48
  "module": "kotlin-stdlib-jdk7",
49
49
  "version": {
50
- "requires": "2.0.21"
50
+ "requires": "2.1.20"
51
51
  }
52
52
  },
53
53
  {
@@ -60,13 +60,13 @@
60
60
  ],
61
61
  "files": [
62
62
  {
63
- "name": "expo.modules.screencapture-7.2.0.aar",
64
- "url": "expo.modules.screencapture-7.2.0.aar",
65
- "size": 28229,
66
- "sha512": "e43057ceb38b0158e6866e120313f3d2f77ced9e1ac025667c2bebe36e528d537a248d4d7bff6c6db7683287ff777e14b651597b26636f7a1170825e35ea25b9",
67
- "sha256": "e530fcfe5b4c0ca8362bc07e085bfd113e6bb5f9798cde28925b64c238ce77eb",
68
- "sha1": "7ecf0a53df33e2c96fb06dd301d6a5e0824282f0",
69
- "md5": "7bd790ffca2e473cce9d80535730ba3c"
63
+ "name": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar",
64
+ "url": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0.aar",
65
+ "size": 28245,
66
+ "sha512": "5d693f6a83cc09074f42ae55d49f7cccfc0c2e1f024e43d866c285e18f0e37648ff966eb7507567538355f6d9f1b6c7d51f6eb45456dbe191ad41f3ae896f930",
67
+ "sha256": "8a9e3dca21a096209a62e8ce26c3733e57135f9d59a41eb237636ae81c744345",
68
+ "sha1": "bff3c51739c45f8a9d1b2184ddfb30538a689344",
69
+ "md5": "3a53f7e2c485ed09380013fe5be379c8"
70
70
  }
71
71
  ]
72
72
  },
@@ -80,8 +80,8 @@
80
80
  },
81
81
  "files": [
82
82
  {
83
- "name": "expo.modules.screencapture-7.2.0-sources.jar",
84
- "url": "expo.modules.screencapture-7.2.0-sources.jar",
83
+ "name": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar",
84
+ "url": "expo.modules.screencapture-7.3.0-canary-20250811-5c940c0-sources.jar",
85
85
  "size": 3601,
86
86
  "sha512": "080676e6818f1d063d27b7b460c49e34d7ebeae5e6a6e4c071840008b10a6beaafe0022467b6f556a1a190b22ae6b04ef87de7e7c2a74364b5af845efa1a6b05",
87
87
  "sha256": "d2c5b19e0bb1ad883b35525cdce5c665213505bea5b758f0c0c44b735fc960eb",
@@ -0,0 +1 @@
1
+ 86d651502027df8185e69e1aa7a0cf87e79507861d2958aa298658f960ef0f4cdc349d7d56346f3cc91c4ec442ff95ae3c8e10c049a6981b4fa44e8feffe101d
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>host.exp.exponent</groupId>
11
11
  <artifactId>expo.modules.screencapture</artifactId>
12
- <version>7.2.0</version>
12
+ <version>7.3.0-canary-20250811-5c940c0</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.screencapture</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -28,7 +28,7 @@
28
28
  <dependency>
29
29
  <groupId>org.jetbrains.kotlin</groupId>
30
30
  <artifactId>kotlin-stdlib-jdk7</artifactId>
31
- <version>2.0.21</version>
31
+ <version>2.1.20</version>
32
32
  <scope>runtime</scope>
33
33
  </dependency>
34
34
  <dependency>
@@ -0,0 +1 @@
1
+ 35e7286147e2c952f0204ce357ada73319921b820bb2cfe016e186e8b598d16eb73410d283025d9b6a460c94b4c8eb8c367b7619d5efe76704aa42021e4243ec
@@ -3,11 +3,11 @@
3
3
  <groupId>host.exp.exponent</groupId>
4
4
  <artifactId>expo.modules.screencapture</artifactId>
5
5
  <versioning>
6
- <latest>7.2.0</latest>
7
- <release>7.2.0</release>
6
+ <latest>7.3.0-canary-20250811-5c940c0</latest>
7
+ <release>7.3.0-canary-20250811-5c940c0</release>
8
8
  <versions>
9
- <version>7.2.0</version>
9
+ <version>7.3.0-canary-20250811-5c940c0</version>
10
10
  </versions>
11
- <lastUpdated>20250723214424</lastUpdated>
11
+ <lastUpdated>20250811152903</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- fd0eb2a064d603d0a6a22df9d654b549
1
+ 25032c5cc649b45027784af048bdb243
@@ -1 +1 @@
1
- a62b47362da90d7f1104046785b26a1f4b438a82
1
+ c93443c525104ec3117e3621b6087345e75eab82
@@ -1 +1 @@
1
- 72e99e6db793eafbc5cde6f85f9dfd0277fb07d342b1bdb85ea0db57ffdc8ccc
1
+ 32e4a8ecf3bcf3eb89edc5a73c722d90600ec5db59130e25743e5c181c739812
@@ -1 +1 @@
1
- cf618eb945609a190d48540b8441f561bbfa31c5017c23c5ace91ef3ede4f369a5529b818d459df6e62276dac5c793366580662e95df31ce3178a01d821cee0a
1
+ c623b2ddabb5d5b8996588e895bd8831bee282f1a26f5d537392fb50099bd163184f3b4b577c115e0bc71460d69806588538826ee19cdc3045fa05d52bd86c05
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-screen-capture",
3
- "version": "7.2.0",
3
+ "version": "7.3.0-canary-20250811-5c940c0",
4
4
  "description": "Protects screens in your app from being captured or recorded, and notifies if a screenshot is taken.",
5
5
  "main": "build/ScreenCapture.js",
6
6
  "types": "build/ScreenCapture.d.ts",
@@ -35,11 +35,10 @@
35
35
  "dependencies": {},
36
36
  "devDependencies": {
37
37
  "@testing-library/react-native": "^13.1.0",
38
- "expo-module-scripts": "^4.1.9"
38
+ "expo-module-scripts": "4.1.11-canary-20250811-5c940c0"
39
39
  },
40
40
  "peerDependencies": {
41
- "expo": "*",
41
+ "expo": "54.0.0-canary-20250811-5c940c0",
42
42
  "react": "*"
43
- },
44
- "gitHead": "365807cb7fa8c0fc7a3f77c1b7bca47cd8dabc55"
43
+ }
45
44
  }
@@ -135,8 +135,12 @@ export async function disableAppSwitcherProtectionAsync(): Promise<void> {
135
135
  // @needsAudit
136
136
  /**
137
137
  * Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded.
138
- * On Android, this method requires the `READ_EXTERNAL_STORAGE` permission. You can request this
139
- * with [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
138
+ *
139
+ * Permission requirements for this method depend on your device’s Android version:
140
+ * - **Before Android 13**: Requires `READ_EXTERNAL_STORAGE`.
141
+ * - **Android 13**: Switches to `READ_MEDIA_IMAGES`.
142
+ * - **Post-Android 13**: No additional permissions required.
143
+ * You can request the appropriate permissions by using [`MediaLibrary.requestPermissionsAsync()`](./media-library/#medialibraryrequestpermissionsasync).
140
144
  *
141
145
  * @param listener The function that will be executed when the user takes a screenshot.
142
146
  * This function accepts no arguments.
@@ -170,6 +174,25 @@ export function removeScreenshotListener(subscription: EventSubscription) {
170
174
  subscription.remove();
171
175
  }
172
176
 
177
+ // @needsAudit
178
+ /**
179
+ * A React hook that listens for screenshots taken while the component is mounted.
180
+ *
181
+ * @param listener A function that will be called whenever a screenshot is detected.
182
+ *
183
+ * This hook automatically starts listening when the component mounts, and stops
184
+ * listening when the component unmounts.
185
+ */
186
+ export function useScreenshotListener(listener: () => void) {
187
+ useEffect(() => {
188
+ const subscription = addScreenshotListener(listener);
189
+
190
+ return () => {
191
+ removeScreenshotListener(subscription);
192
+ };
193
+ }, [listener]);
194
+ }
195
+
173
196
  /**
174
197
  * Checks user's permissions for detecting when a screenshot is taken.
175
198
  * > Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a `granted` permission response.
@@ -1 +0,0 @@
1
- e530fcfe5b4c0ca8362bc07e085bfd113e6bb5f9798cde28925b64c238ce77eb
@@ -1 +0,0 @@
1
- e43057ceb38b0158e6866e120313f3d2f77ced9e1ac025667c2bebe36e528d537a248d4d7bff6c6db7683287ff777e14b651597b26636f7a1170825e35ea25b9
@@ -1 +0,0 @@
1
- eb7942403db36548e2a30843df9603bbd953b62cde3b1d9135b415f6002b8fad
@@ -1 +0,0 @@
1
- 1969bccc451e72966f599308a220a7feb7fbdef19714e739a8cbbf06ca26d73b00cf3977433c4cd1177e3cfecabf968f30cd5ac0def264cdd6fada48c2f4e871
@@ -1 +0,0 @@
1
- 6e1e7ac4258dd4fce62db26f41a1ec3aac14c50fc81ecf77fcff8bcd8cf09c7f
@@ -1 +0,0 @@
1
- dcdb1b3595d48386b5c75a6f5190d9e6df246e0ab5bb3421f03fd53e507d1c0bf91aa108fc4a38483d2b8a472cac687f4a9ea6960d4ec0ecac041e1b60899235