From 3eeeda3e8586c0bd037a62769a17b5c85a0f1318 Mon Sep 17 00:00:00 2001 From: yinjiacheng Date: Mon, 1 Jul 2024 17:25:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ememorywarning=E3=80=81usercap?= =?UTF-8?q?turescreen=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages.json | 12 ++ pages/API/memory-warning/memory-warning.uvue | 53 ++++++ .../user-capture-screen.uvue | 56 +++++++ pages/tabBar/API.uvue | 10 ++ uni_modules/uni-memorywarning/changelog.md | 4 + uni_modules/uni-memorywarning/package.json | 95 +++++++++++ uni_modules/uni-memorywarning/readme.md | 19 +++ .../utssdk/app-android/index.uts | 50 ++++++ .../utssdk/app-ios/index.uts | 47 ++++++ .../uni-memorywarning/utssdk/index.d.ts | 71 ++++++++ .../uni-memorywarning/utssdk/interface.uts | 69 ++++++++ .../uni-usercapturescreen/changelog.md | 10 ++ uni_modules/uni-usercapturescreen/index.d.ts | 157 ++++++++++++++++++ .../uni-usercapturescreen/package.json | 95 +++++++++++ uni_modules/uni-usercapturescreen/readme.md | 21 +++ .../utssdk/app-android/index.uts | 140 ++++++++++++++++ .../utssdk/app-ios/index.uts | 138 +++++++++++++++ .../utssdk/interface.uts | 155 +++++++++++++++++ .../utssdk/mp-weixin/index.js | 7 + .../uni-usercapturescreen/utssdk/unierror.uts | 35 ++++ 20 files changed, 1244 insertions(+) create mode 100644 pages/API/memory-warning/memory-warning.uvue create mode 100644 pages/API/user-capture-screen/user-capture-screen.uvue create mode 100644 uni_modules/uni-memorywarning/changelog.md create mode 100644 uni_modules/uni-memorywarning/package.json create mode 100644 uni_modules/uni-memorywarning/readme.md create mode 100644 uni_modules/uni-memorywarning/utssdk/app-android/index.uts create mode 100644 uni_modules/uni-memorywarning/utssdk/app-ios/index.uts create mode 100644 uni_modules/uni-memorywarning/utssdk/index.d.ts create mode 100644 uni_modules/uni-memorywarning/utssdk/interface.uts create mode 100644 uni_modules/uni-usercapturescreen/changelog.md create mode 100644 uni_modules/uni-usercapturescreen/index.d.ts create mode 100644 uni_modules/uni-usercapturescreen/package.json create mode 100644 uni_modules/uni-usercapturescreen/readme.md create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/interface.uts create mode 100644 uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js create mode 100644 uni_modules/uni-usercapturescreen/utssdk/unierror.uts diff --git a/pages.json b/pages.json index 6587e4a3..3c0b97d5 100644 --- a/pages.json +++ b/pages.json @@ -720,6 +720,18 @@ "navigationBarTitleText": "get-app-authorize-setting" } }, + { + "path": "pages/API/memory-warning/memory-warning", + "style": { + "navigationBarTitleText" : "内存" + } + }, + { + "path": "pages/API/user-capture-screen/user-capture-screen", + "style": { + "navigationBarTitleText" : "截屏事件" + } + }, // #endif { "path": "pages/API/preview-image/preview-image", diff --git a/pages/API/memory-warning/memory-warning.uvue b/pages/API/memory-warning/memory-warning.uvue new file mode 100644 index 00000000..8b499384 --- /dev/null +++ b/pages/API/memory-warning/memory-warning.uvue @@ -0,0 +1,53 @@ + + + + + \ No newline at end of file diff --git a/pages/API/user-capture-screen/user-capture-screen.uvue b/pages/API/user-capture-screen/user-capture-screen.uvue new file mode 100644 index 00000000..cf2040ac --- /dev/null +++ b/pages/API/user-capture-screen/user-capture-screen.uvue @@ -0,0 +1,56 @@ + + + + + \ No newline at end of file diff --git a/pages/tabBar/API.uvue b/pages/tabBar/API.uvue index 99cae142..57672651 100644 --- a/pages/tabBar/API.uvue +++ b/pages/tabBar/API.uvue @@ -287,6 +287,16 @@ name: '安装Apk', url: 'install-apk' }, + // #endif + // #ifdef APP + { + name: '内存', + url: 'memory-warning' + }, + { + name: '截屏事件', + url: 'user-capture-screen' + }, // #endif // #ifdef WEB { diff --git a/uni_modules/uni-memorywarning/changelog.md b/uni_modules/uni-memorywarning/changelog.md new file mode 100644 index 00000000..7c1cb3d5 --- /dev/null +++ b/uni_modules/uni-memorywarning/changelog.md @@ -0,0 +1,4 @@ +## 1.1.0(2022-12-05) +实现iOS平台内存警告监听 +## 1.0.0(2022-11-12) +实现Android平台内存警告监听功能 diff --git a/uni_modules/uni-memorywarning/package.json b/uni_modules/uni-memorywarning/package.json new file mode 100644 index 00000000..9bda0f8f --- /dev/null +++ b/uni_modules/uni-memorywarning/package.json @@ -0,0 +1,95 @@ +{ + "id": "uni-memorywarning", + "displayName": "uni-MemoryWarning", + "version": "1.1.0", + "description": "UTS 实现内存警告监听", + "keywords": [ + "onMemoryWarning" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.6.11" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "uni-ext-api": { + "uni": { + "onMemoryWarning": { + "web": false + }, + "offMemoryWarning": { + "web": false + } + } + }, + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "19" + }, + "app-ios": { + "minVersion": "9" + } + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} diff --git a/uni_modules/uni-memorywarning/readme.md b/uni_modules/uni-memorywarning/readme.md new file mode 100644 index 00000000..61953801 --- /dev/null +++ b/uni_modules/uni-memorywarning/readme.md @@ -0,0 +1,19 @@ +## 使用说明 + +### uni.onMemoryWarning(CALLBACK) + +监听内存不足告警事件,当系统应用进程发出内存警告时,触发该事件。 + +> 使用文档:[https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning](https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning) + +**注意平台差异:仅Android平台有返回值,iOS平台无返回值** + + +### uni.offMemoryWarning(CALLBACK) + +取消监听内存不足告警事件。 + +onMemoryWarning 传入的监听函数。不传此参数则移除所有监听函数。 + +> 使用文档:[https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning](https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning) + diff --git a/uni_modules/uni-memorywarning/utssdk/app-android/index.uts b/uni_modules/uni-memorywarning/utssdk/app-android/index.uts new file mode 100644 index 00000000..ec4a9106 --- /dev/null +++ b/uni_modules/uni-memorywarning/utssdk/app-android/index.uts @@ -0,0 +1,50 @@ +import { UTSAndroid } from "io.dcloud.uts" +import { OnMemoryWarning, OffMemoryWarning, MemoryWarningCallback, MemoryWarningCallbackResult } from "../interface.uts" + +let listeners: MemoryWarningCallback[] = [] + +const onAppTrimMemoryListener = (ret: number) => { + listeners.forEach(listener => { + let res: MemoryWarningCallbackResult = { + level:ret + } + listener(res) + }) +} + + +@Suppress("DEPRECATION") +export const onMemoryWarning : OnMemoryWarning = function (callback: MemoryWarningCallback) { + if (listeners.length == 0) { + // 仅首次执行底层的实际监听 + UTSAndroid.onAppTrimMemory(onAppTrimMemoryListener) + UTSAndroid.onAppActivityDestroy(()=>{ + // listeners 默认是静态常量周期,activity 销毁时,需要手动清空 + listeners = [] + }) + } + listeners.push(callback) +} + + +@Suppress("DEPRECATION") +export const offMemoryWarning : OffMemoryWarning = function (callback: MemoryWarningCallback | null) { + + if(callback == null){ + // 清除全部回调 + listeners = [] + UTSAndroid.offAppTrimMemory(null); + return + } + + // 清除指定回调 + const index = listeners.indexOf(callback) + if (index > -1) { + listeners.splice(index, 1) + } + if (listeners.length == 0) { + // 当用户不再监听时,移除底层实际监听 + UTSAndroid.offAppTrimMemory(onAppTrimMemoryListener) + } +} + diff --git a/uni_modules/uni-memorywarning/utssdk/app-ios/index.uts b/uni_modules/uni-memorywarning/utssdk/app-ios/index.uts new file mode 100644 index 00000000..5f4f37bf --- /dev/null +++ b/uni_modules/uni-memorywarning/utssdk/app-ios/index.uts @@ -0,0 +1,47 @@ +import { NotificationCenter } from 'Foundation'; +import { UIApplication } from "UIKit" +import { Selector } from "ObjectiveC" +import { OnMemoryWarning, OffMemoryWarning, MemoryWarningCallback, MemoryWarningCallbackResult } from "../interface.uts" + +class MemoryWarningTool { + static listener: MemoryWarningCallback | null = null + // 监听内存警告 + static listenMemoryWarning(callback: MemoryWarningCallback) { + + // 只有首次才需要注册监听事件 + if (this.listener == null) { + // 注册监听内存警告通知事件及设置回调方法 + // target-action 回调方法需要通过 Selector("方法名") 构建 + const method = Selector("receiveMemoryWarning") + NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.didReceiveMemoryWarningNotification, object = null) + } + this.listener = callback + } + + // 内存警告回调的方法 + // target-action 的方法前需要添加 @objc 前缀 + @objc static receiveMemoryWarning() { + // 触发回调 + let res: MemoryWarningCallbackResult = { + level: 0 + }; + this.listener?.(res); + } + + // 移除监听事件 + static removeListen(callback: MemoryWarningCallback | null) { + this.listener = null; + NotificationCenter.default.removeObserver(this) + } +} + + +// 开启监听内存警告 +export const onMemoryWarning : OnMemoryWarning = function (callback: MemoryWarningCallback) { + MemoryWarningTool.listenMemoryWarning(callback) +} + +// 关闭监听内存警告 +export const offMemoryWarning : OffMemoryWarning = function (callback: MemoryWarningCallback | null) { + MemoryWarningTool.removeListen(callback) +} diff --git a/uni_modules/uni-memorywarning/utssdk/index.d.ts b/uni_modules/uni-memorywarning/utssdk/index.d.ts new file mode 100644 index 00000000..08067edc --- /dev/null +++ b/uni_modules/uni-memorywarning/utssdk/index.d.ts @@ -0,0 +1,71 @@ +declare namespace UniNamespace { + +interface MemoryWarningCallbackResult { + /** + * 内存警告等级(仅安卓平台有效,iOS始终是0) + */ + level: number +} + +/** + * uni.onMemoryWarning/uni.offMemoryWarning回调函数定义 + */ +type MemoryWarningCallback = (res: MemoryWarningCallbackResult) => void + +type OnMemoryWarning = (callback: MemoryWarningCallback) => void + +type OffMemoryWarning = (callback : MemoryWarningCallback | null) => void + +} + + +declare interface Uni { + /** + * 开启监听内存警告 + * + * @param {MemoryWarningCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "9.0", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + onMemoryWarning(callback: UniNamespace.MemoryWarningCallback) : void, + /** + * 取消监听内存不足告警事件 + * + * @param {MemoryWarningCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "9.0", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + offMemoryWarning(callback : UniNamespace.MemoryWarningCallback | null) : void +} diff --git a/uni_modules/uni-memorywarning/utssdk/interface.uts b/uni_modules/uni-memorywarning/utssdk/interface.uts new file mode 100644 index 00000000..5a607d53 --- /dev/null +++ b/uni_modules/uni-memorywarning/utssdk/interface.uts @@ -0,0 +1,69 @@ +/** + * uni.onMemoryWarning/uni.offMemoryWarning回调参数 + */ +export type MemoryWarningCallbackResult = { + /** + * 内存警告等级(仅安卓平台有效,iOS始终是0) + */ + level: number +} + +/** + * uni.onMemoryWarning/uni.offMemoryWarning回调函数定义 + */ +export type MemoryWarningCallback = (res: MemoryWarningCallbackResult) => void + +export type OnMemoryWarning = (callback: MemoryWarningCallback) => void + +export type OffMemoryWarning = (callback : MemoryWarningCallback | null) => void + +export interface Uni { + /** + * 开启监听内存警告 + * + * @param {MemoryWarningCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "12.0", + * "uniVer": "3.7.7", + * "unixVer": "4.11" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + onMemoryWarning(callback: MemoryWarningCallback) : void, + /** + * 取消监听内存不足告警事件 + * + * @param {MemoryWarningCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "12.0", + * "uniVer": "3.7.7", + * "unixVer": "4.11" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + offMemoryWarning(callback : MemoryWarningCallback | null) : void +} diff --git a/uni_modules/uni-usercapturescreen/changelog.md b/uni_modules/uni-usercapturescreen/changelog.md new file mode 100644 index 00000000..51378b54 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/changelog.md @@ -0,0 +1,10 @@ +## 1.0.4(2023-03-24) +新增开启/关闭防截屏功能 +## 1.0.3(2023-03-17) +修复android平台 部分场景下js可能报错的问题 +## 1.0.2(2023-03-16) +修复Android平台在小米设备无法监听的问题 修复Android平台调用uni.onUserCaptureScreen必然会触发回调的问题 +## 1.0.1(2022-10-27) +修改插件描述 +## 1.0.0(2022-10-26) +支持安卓、iOS、微信小程序平台 diff --git a/uni_modules/uni-usercapturescreen/index.d.ts b/uni_modules/uni-usercapturescreen/index.d.ts new file mode 100644 index 00000000..dbb3f929 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/index.d.ts @@ -0,0 +1,157 @@ +declare namespace UniNamespace { + /** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数 + */ + type OnUserCaptureScreenCallbackResult = { + /** + * 截屏文件路径(仅Android返回) + */ + path ?: string + } + + /** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义 + */ + type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void + + type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + + type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + + /** + * uni.setUserCaptureScreen成功回调参数 + */ + type SetUserCaptureScreenSuccess = { + + } + + /** + * uni.setUserCaptureScreen成功回调函数定义 + */ + type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void + + /** + * 错误码 + * - 12001 "setUserCaptureScreen:system not support" + * - 12010 "setUserCaptureScreen:system internal error" + */ + type SetUserCaptureScreenErrorCode = 12001 | 12010; + + /** + * SetUserCaptureScreen 的错误回调参数 + */ + interface SetUserCaptureScreenFail { + errCode : SetUserCaptureScreenErrorCode + } + + /** + * uni.setUserCaptureScreen失败回调函数定义 + */ + type SetUserCaptureScreenFailCallback = (res : SetUserCaptureScreenFail) => void + + /** + * uni.setUserCaptureScreen完成回调函数定义 + */ + type SetUserCaptureScreenCompleteCallback = (res : any) => void + + /** + * uni.setUserCaptureScreen参数 + */ + type SetUserCaptureScreenOptions = { + /** + * true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容 + */ + enable : boolean; + /** + * 接口调用成功的回调函数 + */ + // success : SetUserCaptureScreenSuccessCallback | null, + success ?: SetUserCaptureScreenSuccessCallback, + /** + * 接口调用失败的回调函数 + */ + // fail : SetUserCaptureScreenFailCallback | null, + fail ?: SetUserCaptureScreenFailCallback, + /** + * 接口调用结束的回调函数(调用成功、失败都会执行) + */ + // complete : SetUserCaptureScreenSuccessCallback | SetUserCaptureScreenFailCallback | null + complete ?: SetUserCaptureScreenCompleteCallback + } + + type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void +} + +declare interface Uni { + /** + * 开启截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "9.0", + * "uniVer": "3.7.7", + * "unixVer": "x" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + onUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void, + /** + * 关闭截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "9.0", + * "uniVer": "3.7.7", + * "unixVer": "x" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + offUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void, + /** + * 设置防截屏 + * + * @param {SetUserCaptureScreenOptions} options + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "13.0", + * "uniVer": "3.7.7", + * "unixVer": "x" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + */ + setUserCaptureScreen(options : UniNamespace.SetUserCaptureScreenOptions) : void +} diff --git a/uni_modules/uni-usercapturescreen/package.json b/uni_modules/uni-usercapturescreen/package.json new file mode 100644 index 00000000..c55c0f8c --- /dev/null +++ b/uni_modules/uni-usercapturescreen/package.json @@ -0,0 +1,95 @@ +{ + "id": "uni-usercapturescreen", + "displayName": "uni-usercapturescreen", + "version": "1.0.4", + "description": "用户主动截屏事件监听", + "keywords": [ + "截屏" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.7.7" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "uni-ext-api":{ + "uni": { + "onUserCaptureScreen": { + "web": false + }, + "offUserCaptureScreen": { + "web": false + }, + "setUserCaptureScreen": { + "web": false, + "mp-weixin": false + } + } + }, + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-android": "y", + "app-ios": "y" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "y", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} diff --git a/uni_modules/uni-usercapturescreen/readme.md b/uni_modules/uni-usercapturescreen/readme.md new file mode 100644 index 00000000..eda987aa --- /dev/null +++ b/uni_modules/uni-usercapturescreen/readme.md @@ -0,0 +1,21 @@ +# uni-usercapturescreen + +用户主动截屏事件监听 + +### uni.onUserCaptureScreen + +监听用户主动截屏事件,用户使用系统截屏按键截屏时触发此事件。 + +> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen) + +### uni.offUserCaptureScreen + +用户主动截屏事件。取消事件监听。 + +> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen) + +### uni.setUserCaptureScreen + +开启/关闭防截屏。 + +> 使用文档:[https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen) diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts new file mode 100644 index 00000000..14bceba1 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts @@ -0,0 +1,140 @@ +import { UTSAndroid } from "io.dcloud.uts"; +import ActivityCompat from "androidx.core.app.ActivityCompat"; +import Manifest from "android.Manifest"; +import PackageManager from "android.content.pm.PackageManager"; +import Build from "android.os.Build"; +import FileObserver from "android.os.FileObserver"; +import File from "java.io.File"; +import Environment from "android.os.Environment"; +import System from 'java.lang.System'; +import WindowManager from 'android.view.WindowManager'; +import { OnUserCaptureScreenCallbackResult, UserCaptureScreenCallback, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreenSuccess, SetUserCaptureScreenOptions, SetUserCaptureScreen } from "../interface.uts"; +import string from 'android.R.string'; + + +/** + * 文件监听器 + */ +let observer : ScreenFileObserver | null = null; +/** + * 记录文件监听器上次监听的时间戳,避免重复监听 + */ +let lastObserverTime : number = 0; +/** + * 截屏回调 + */ +let listener : UserCaptureScreenCallback | null = null; + +/** + * android 文件监听实现 + */ +@Suppress("DEPRECATION") +class ScreenFileObserver extends FileObserver { + + /** + * 截屏文件目录 + */ + private screenFile : File; + + constructor(screenFileStr : string) { + super(screenFileStr); + this.screenFile = new File(screenFileStr); + } + + override onEvent(event : Int, path : string | null) : void { + // 只监听文件新增事件 + if (event == FileObserver.CREATE) { + if (path != null) { + const currentTime = System.currentTimeMillis(); + if ((currentTime - lastObserverTime) < 1000) { + // 本地截屏行为比上一次超过1000ms, 才认为是一个有效的时间 + return; + } + lastObserverTime = currentTime; + + const screenShotPath = new File(this.screenFile, path).getPath(); + const res : OnUserCaptureScreenCallbackResult = { + path: screenShotPath + } + listener?.(res); + } + } + } +} + +/** + * 开启截图监听 + */ +export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { + UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, [Manifest.permission.READ_EXTERNAL_STORAGE], function (allRight : boolean, _ : string[]) { + if (allRight) { + // 更新监听 + listener = callback; + + let directory_screenshot : File; + if (Build.MANUFACTURER.toLowerCase() == "xiaomi") { + // @Suppress("DEPRECATION") + directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM), "Screenshots"); + } else { + // @Suppress("DEPRECATION") + directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES), "Screenshots"); + } + // 先结束监听 再开启监听 + observer?.stopWatching(); + observer = new ScreenFileObserver(directory_screenshot.getPath()); + observer?.startWatching(); + + UTSAndroid.onAppActivityDestroy(function () { + observer?.stopWatching(); + observer = null; + }); + } + }, function (doNotAskAgain : boolean, _ : string[]) { + if (doNotAskAgain) { + UTSAndroid.gotoSystemPermissionActivity(UTSAndroid.getUniActivity()!, [Manifest.permission.READ_EXTERNAL_STORAGE]); + } + }); +} + +/** + * 关闭截屏监听 + */ +export const offUserCaptureScreen : OffUserCaptureScreen = function (_ : UserCaptureScreenCallback | null) { + // android10以上,关闭监听通过移除文件监听器实现 + observer?.stopWatching(); + observer = null; + lastObserverTime = 0; +} + +/** + * 设置是否禁止截屏 + */ +export const setUserCaptureScreen : SetUserCaptureScreen = function (option : SetUserCaptureScreenOptions) { + // 切换到UI线程 + UTSAndroid.getUniActivity()?.runOnUiThread(new SetUserCaptureScreenRunnable(option.enable)); + const res : SetUserCaptureScreenSuccess = {} + option.success?.(res); + option.complete?.(res); +} + +class SetUserCaptureScreenRunnable extends Runnable { + + /** + * ture: 允许用户截屏 + * false: 不允许用户截屏,防止用户截屏到应用页面内容 + */ + private enable : boolean; + + constructor(enable : boolean) { + super(); + this.enable = enable; + } + + override run() : void { + if (this.enable) { + UTSAndroid.getUniActivity()?.getWindow()?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE); + } else { + UTSAndroid.getUniActivity()?.getWindow()?.addFlags(WindowManager.LayoutParams.FLAG_SECURE); + } + } +} diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts new file mode 100644 index 00000000..bb649b48 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts @@ -0,0 +1,138 @@ +import { NotificationCenter } from 'Foundation'; +import { CGRect } from "CoreFoundation"; +import { UIApplication, UIView, UITextField, UIScreen, UIDevice } from "UIKit" +import { UTSiOS } from "DCloudUTSFoundation" +import { DispatchQueue } from 'Dispatch'; +import { SetUserCaptureScreenOptions, OnUserCaptureScreenCallbackResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen, UserCaptureScreenCallback, SetUserCaptureScreenSuccess } from "../interface.uts" +import { SetUserCaptureScreenFailImpl } from "../unierror.uts" +/** + * 定义监听截屏事件工具类 + */ +class CaptureScreenTool { + static listener : UserCaptureScreenCallback | null; + static secureView : UIView | null; + + // 监听截屏 + static listenCaptureScreen(callback : UserCaptureScreenCallback | null) { + this.listener = callback + + // 注册监听截屏事件及回调方法 + // target-action 回调方法需要通过 Selector("方法名") 构建 + const method = Selector("userDidTakeScreenshot") + NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.userDidTakeScreenshotNotification, object = null) + } + + // 捕获截屏回调的方法 + // target-action 的方法前需要添加 @objc 前缀 + @objc static userDidTakeScreenshot() { + // 回调 + const res: OnUserCaptureScreenCallbackResult = { + } + this.listener?.(res) + } + + // 移除监听事件 + static removeListen(callback : UserCaptureScreenCallback | null) { + this.listener = null + NotificationCenter.default.removeObserver(this) + } + + static createSecureView() : UIView | null { + let field = new UITextField(frame = CGRect.zero) + field.isSecureTextEntry = true + if (field.subviews.length > 0 && UIDevice.current.systemVersion != '15.1') { + let view = field.subviews[0] + view.subviews.forEach((item) => { + item.removeFromSuperview() + }) + view.isUserInteractionEnabled = true + return view + } + return null + } + + // 开启防截屏 + static onAntiScreenshot(option : SetUserCaptureScreenOptions) { + // uts方法默认会在子线程中执行,涉及 UI 操作必须在主线程中运行,通过 DispatchQueue.main.async 方法可将代码在主线程中运行 + DispatchQueue.main.async(execute = () : void => { + let secureView = this.createSecureView() + let window = UTSiOS.getKeyWindow() + let rootView = window.rootViewController == null ? null : window.rootViewController!.view + if (secureView != null && rootView != null) { + let rootSuperview = rootView!.superview + if (rootSuperview != null) { + this.secureView = secureView + rootSuperview!.addSubview(secureView!) + rootView!.removeFromSuperview() + secureView!.addSubview(rootView!) + let rect = rootView!.frame + secureView!.frame = UIScreen.main.bounds + rootView!.frame = rect + } + } + let res: SetUserCaptureScreenSuccess = { + } + option.success?.(res) + option.complete?.(res) + }) + } + + // 关闭防截屏 + static offAntiScreenshot(option : SetUserCaptureScreenOptions) { + DispatchQueue.main.async(execute = () : void => { + if (this.secureView != null) { + let window = UTSiOS.getKeyWindow() + let rootView = window.rootViewController == null ? null : window.rootViewController!.view + if (rootView != null && this.secureView!.superview != null) { + let rootSuperview = this.secureView!.superview + if (rootSuperview != null) { + rootSuperview!.addSubview(rootView!) + this.secureView!.removeFromSuperview() + } + } + this.secureView = null + } + let res: SetUserCaptureScreenSuccess = { + } + option.success?.(res) + option.complete?.(res) + }) + } +} + +/** + * 开启截图监听 + */ +export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { + CaptureScreenTool.listenCaptureScreen(callback) +} + +/** + * 关闭截屏监听 + */ +export const offUserCaptureScreen : OffUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { + CaptureScreenTool.removeListen(callback) +} + +/** + * 开启/关闭防截屏 + */ +export const setUserCaptureScreen : SetUserCaptureScreen = function (options : SetUserCaptureScreenOptions) { + if (UIDevice.current.systemVersion < "13.0") { + let res = new SetUserCaptureScreenFailImpl(12001) + options.fail?.(res); + options.complete?.(res); + + } else if (UIDevice.current.systemVersion == "15.1") { + let res = new SetUserCaptureScreenFailImpl(12010) + options.fail?.(res); + options.complete?.(res); + } else { + if (options.enable == true) { + CaptureScreenTool.offAntiScreenshot(options) + } else { + CaptureScreenTool.onAntiScreenshot(options) + } + } +} + diff --git a/uni_modules/uni-usercapturescreen/utssdk/interface.uts b/uni_modules/uni-usercapturescreen/utssdk/interface.uts new file mode 100644 index 00000000..73e5514a --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/interface.uts @@ -0,0 +1,155 @@ +/** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数 + */ +export type OnUserCaptureScreenCallbackResult = { + /** + * 截屏文件路径(仅Android返回) + */ + path ?: string +} + +/** + * uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义 + */ +export type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void + +export type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + +export type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void + +/** + * uni.setUserCaptureScreen成功回调参数 + */ +export type SetUserCaptureScreenSuccess = { +} + + +/** + * uni.setUserCaptureScreen成功回调函数定义 + */ +export type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void + +/** + * uni.setUserCaptureScreen失败回调函数定义 + */ +export type SetUserCaptureScreenFailCallback = (res : UniError) => void + +/** + * uni.setUserCaptureScreen完成回调函数定义 + */ +export type SetUserCaptureScreenCompleteCallback = (res : any) => void + +/** + * uni.setUserCaptureScreen参数 + */ + +export type SetUserCaptureScreenOptions = { + /** + * true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容 + */ + enable : boolean; + /** + * 接口调用成功的回调函数 + */ + // success : SetUserCaptureScreenSuccessCallback | null, + success ?: SetUserCaptureScreenSuccessCallback, + /** + * 接口调用失败的回调函数 + */ + // fail : SetUserCaptureScreenFailCallback | null, + fail ?: SetUserCaptureScreenFailCallback, + /** + * 接口调用结束的回调函数(调用成功、失败都会执行) + */ + // complete : SetUserCaptureScreenSuccessCallback | SetUserCaptureScreenFailCallback | null + complete ?: SetUserCaptureScreenCompleteCallback +} + +/** + * 错误码 + * - 12001 "setUserCaptureScreen:system not support" + * - 12010 "setUserCaptureScreen:system internal error" + */ +export type SetUserCaptureScreenErrorCode = 12001 | 12010; +/** + * SetUserCaptureScreen 的错误回调参数 + */ +export interface SetUserCaptureScreenFail extends IUniError { + errCode : SetUserCaptureScreenErrorCode +}; + +export type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void + +export interface Uni { + /** + * 开启截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "12.0", + * "uniVer": "3.7.7", + * "unixVer": "4.11" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + onUserCaptureScreen(callback : UserCaptureScreenCallback | null) : void, + /** + * 关闭截屏监听 + * + * @param {UserCaptureScreenCallback} callback + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "12.0", + * "uniVer": "3.7.7", + * "unixVer": "4.11" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + * @autotest { expectCallback: true } + */ + offUserCaptureScreen(callback : UserCaptureScreenCallback | null) : void, + /** + * 设置防截屏 + * + * @param {SetUserCaptureScreenOptions} options + * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen + * @uniPlatform { + * "app": { + * "android": { + * "osVer": "4.4.4", + * "uniVer": "3.7.7", + * "unixVer": "3.9.0" + * }, + * "ios": { + * "osVer": "13.0", + * "uniVer": "3.7.7", + * "unixVer": "4.11" + * } + * } + * } + * @uniVersion 3.7.7 + * @uniVueVersion 2,3 //支持的vue版本 + */ + setUserCaptureScreen(options : SetUserCaptureScreenOptions) : void +} diff --git a/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js b/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js new file mode 100644 index 00000000..6aa57b32 --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/mp-weixin/index.js @@ -0,0 +1,7 @@ +export function onUserCaptureScreen (callback) { + return wx.onUserCaptureScreen(callback) +} + +export function offUserCaptureScreen (callback) { + return wx.offUserCaptureScreen(callback) +} diff --git a/uni_modules/uni-usercapturescreen/utssdk/unierror.uts b/uni_modules/uni-usercapturescreen/utssdk/unierror.uts new file mode 100644 index 00000000..0f359a8c --- /dev/null +++ b/uni_modules/uni-usercapturescreen/utssdk/unierror.uts @@ -0,0 +1,35 @@ +import { SetUserCaptureScreenErrorCode, SetUserCaptureScreenFail } from "./interface.uts" +/** + * 错误主题 + */ +export const UniErrorSubject = 'uni-usercapturescreen'; + + +/** + * 错误信息 + * @UniError + */ +export const UniErrors : Map = new Map([ + /** + * 错误码及对应的错误信息 + */ + [12001, 'setUserCaptureScreen:system not support'], + [12010, 'setUserCaptureScreen:system internal error'], +]); + + +/** + * 错误对象实现 + */ +export class SetUserCaptureScreenFailImpl extends UniError implements SetUserCaptureScreenFail { + + /** + * 错误对象构造函数 + */ + constructor(errCode : SetUserCaptureScreenErrorCode) { + super(); + this.errSubject = UniErrorSubject; + this.errCode = errCode; + this.errMsg = UniErrors[errCode] ?? ""; + } +} \ No newline at end of file -- GitLab