diff --git a/pages/index/index.vue b/pages/index/index.vue index 93847db613ebab7e157390c365c81ca2fcf43d76..fb405a135cdf1e01aa5800b13f1dd957afbb8619 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -28,7 +28,8 @@ title: 'Hello', memListener:null, setUserCaptureScreenFlag: false, - setUserCaptureScreenText: '禁止截屏' + setUserCaptureScreenText: '禁止截屏', + permissionGranted: false } }, onLoad() { @@ -142,13 +143,9 @@ // 除android 之外的平台,不需要判断返回状态码 if(res.errCode == -1){ // 启动失败 + that.permissionGranted = true; return ; }else if(res.errCode == 0){ - uni.showToast({ - icon:"none", - title:'截屏监听已开启' - }) - }else { uni.showToast({ icon:"none", title:'捕获截屏事件' @@ -164,7 +161,7 @@ } }); - if (uni.getSystemInfoSync().platform != "android") { + if (uni.getSystemInfoSync().platform != "android" || that.permissionGranted) { // 除android 之外的平台,直接提示监听已开启 uni.showToast({ icon:"none", @@ -198,13 +195,13 @@ uni.setUserCaptureScreen({ enable: flag, success: (res) => { - console.log("setUserCaptureScreen open: " + flag + " success: " + JSON.stringify(res)); + console.log("setUserCaptureScreen enable: " + flag + " success: " + JSON.stringify(res)); }, fail: (res) => { - console.log("setUserCaptureScreen open: " + flag + " fail: " + JSON.stringify(res)); + console.log("setUserCaptureScreen enable: " + flag + " fail: " + JSON.stringify(res)); }, complete: (res) => { - console.log("setUserCaptureScreen open: " + flag + " complete: " + JSON.stringify(res)); + console.log("setUserCaptureScreen enable: " + flag + " complete: " + JSON.stringify(res)); } }); uni.showToast({ diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts index 114cde59e082e2134e0dfc52de303db8917ad86f..2a99ed36e376c54f15734b03bf387c3ec86ab7cd 100644 --- a/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts +++ b/uni_modules/uni-usercapturescreen/utssdk/app-android/index.uts @@ -1,10 +1,4 @@ - - -import { - UTSAndroid -} from "io.dcloud.uts"; - - +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"; @@ -14,167 +8,134 @@ 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 { SetUserCaptureScreenOption, UserCaptureScreenResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen } from "../interface.uts"; - - +import { UserCaptureScreenResult, OnUserCaptureScreenResult, SetUserCaptureScreenOptions, UserCaptureScreenCallback, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen } from "../interface.uts"; /** - * 文件监听器 - */ -let screenOB: ScreenFileObserver | null = null; + * 文件监听器 + */ +let observer : ScreenFileObserver | null = null; /** - * 记录文件监听器上次监听的时间戳,避免重复监听 - */ -let lastFileObserverTime: number = 0; + * 记录文件监听器上次监听的时间戳,避免重复监听 + */ +let lastObserverTime : number = 0; /** - * 图片被捕获的实现 - */ -let imageChange: UTSCallback | null = null; - - - + * 截屏回调 + */ +let listener : UserCaptureScreenCallback | null = null; /** - * android 文件监听实现 - */ -@Suppress("DEPRECATION") + * android 文件监听实现 + */ class ScreenFileObserver extends FileObserver { /** - * 所有截屏文件的存放目录 - */ - allScreen: File; + * 截屏文件目录 + */ + private screenFile : File; - - constructor(screenFile: string) { - super(new File(screenFile)) - this.allScreen = new File(screenFile); - + constructor(screenFile : File) { + super(screenFile); + this.screenFile = screenFile; } - - override onEvent(event: Int, path?: string): void { - + override onEvent(event : Int, path : string | null) : void { // 只监听文件新增事件 if (event == FileObserver.CREATE) { - - let newPath: string = new File(this.allScreen, path!).getPath(); - let currentTime = System.currentTimeMillis(); - - if ((currentTime - lastFileObserverTime) < 1000) { - // 本地截屏行为比上一次超过1000ms,才认为是一个有效的时间 - return; - } - - lastFileObserverTime = System.currentTimeMillis() - let ret = { - errCode:1, - image:newPath + 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 : OnUserCaptureScreenResult = { + errCode: 0, + errMsg: "onUserCaptureScreen:ok", + errSubject: "uni-onUserCaptureScreen", + path: screenShotPath + } + listener?.(res); } - - imageChange!(ret); } } } - - - - - - - /** - * 开启截图监听 - */ -@Suppress("DEPRECATION") -export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UTSCallback) { - - // 检查相关权限是否已经具备 - if (ActivityCompat.checkSelfPermission(UTSAndroid.getUniActivity()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - // 不具备权限,申请权限,并且告知用户监听失败 - ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001) - + * 开启截图监听 + */ +export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { + // 检查相关权限是否已授予 + if (ActivityCompat.checkSelfPermission(UTSAndroid.getAppContext()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + // 无权限,申请权限,并且告知用户监听失败 + ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001); // 因权限缺失导致监听失败 - let ret = { - errCode:-1 + const res : OnUserCaptureScreenResult = { + errCode: -1, + errMsg: "onUserCaptureScreen:permission denied", + errSubject: "uni-onUserCaptureScreen" } - callback(ret); - return ; + callback?.(res); + return; } - - imageChange = callback; - let directory_screenshot: File; - // 找到设备存放截屏文件的目录 - let directory_pictures = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES); - let directory_dcim = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM); - + // 更新监听 + listener = callback; + + let directory_screenshot : File; if (Build.MANUFACTURER.toLowerCase() === "xiaomi") { - directory_screenshot = new File(directory_dcim, "Screenshots"); + // @Suppress("DEPRECATION") + directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM), "Screenshots"); } else { - directory_screenshot = new File(directory_pictures, "Screenshots"); + // @Suppress("DEPRECATION") + directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES), "Screenshots"); } - - if (screenOB != null) { - screenOB!.stopWatching() - } - //开始监听 - screenOB = new ScreenFileObserver(directory_screenshot.path) - screenOB!.startWatching() - - // 监听成功 - let ret = { - errCode:0 - } - callback(ret); - + // 先结束监听 再开启监听 + observer?.stopWatching(); + observer = new ScreenFileObserver(directory_screenshot); + observer?.startWatching(); } - /** - * 关闭截屏监听 - */ -export const offUserCaptureScreen : OffUserCaptureScreen = function (callback : UTSCallback) { - - // android 10以上,关闭监听通过移除文件监听器实现 - if (screenOB != null) { - screenOB!.stopWatching() - screenOB = null - } - lastFileObserverTime = 0; - - callback({}); + * 关闭截屏监听 + */ +export const offUserCaptureScreen : OffUserCaptureScreen = function (_ : UserCaptureScreenCallback | null) { + // android10以上,关闭监听通过移除文件监听器实现 + observer?.stopWatching(); + observer = null; + lastObserverTime = 0; } /** - * 设置是否禁止截屏 - */ -export const setUserCaptureScreen : SetUserCaptureScreen = function (option: SetUserCaptureScreenOption) { + * 设置是否禁止截屏 + */ +export const setUserCaptureScreen : SetUserCaptureScreen = function (option : SetUserCaptureScreenOptions) { // 切换到UI线程 UTSAndroid.getUniActivity()?.runOnUiThread(new SetUserCaptureScreenRunnable(option.enable)); - const res = new UserCaptureScreenResult(); - res.errCode = 0; - res.errMsg = "setUserCaptureScreen:ok"; - res.errSubject = "uni-setUserCaptureScreen"; + const res : UserCaptureScreenResult = { + errCode: 0, + errMsg: "setUserCaptureScreen:ok", + errSubject: "uni-setUserCaptureScreen" + } option.success?.(res); option.complete?.(res); } class SetUserCaptureScreenRunnable extends Runnable { - + /** - * ture: 允许用户截屏 - * false: 不允许用户截屏,防止用户截屏到应用页面内容 - */ - private enable: boolean; + * ture: 允许用户截屏 + * false: 不允许用户截屏,防止用户截屏到应用页面内容 + */ + private enable : boolean; - constructor(enable: boolean) { + constructor(enable : boolean) { super(); this.enable = enable; } - override run(): void { + override run() : void { if (this.enable) { UTSAndroid.getUniActivity()?.getWindow()?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE); } else { @@ -182,6 +143,3 @@ class SetUserCaptureScreenRunnable extends Runnable { } } } - - - diff --git a/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts index 1750494f89aa0fb58224108a291fcf09dd9d260d..f197ffeeea89a25ab2fca8bdff571d0239aa6e9e 100644 --- a/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts +++ b/uni_modules/uni-usercapturescreen/utssdk/app-ios/index.uts @@ -1,21 +1,21 @@ import { NotificationCenter } from 'Foundation'; import { CGRect } from "CoreFoundation"; import { UIApplication, UIView, UITextField, UIScreen, UIDevice } from "UIKit" -import { UTSiOS, UTSCallback } from "DCloudUTSFoundation" +import { UTSiOS } from "DCloudUTSFoundation" import { DispatchQueue } from 'Dispatch'; -import { SetUserCaptureScreenOption, UserCaptureScreenResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen } from "../interface.uts" +import { SetUserCaptureScreenOptions, UserCaptureScreenResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen, UserCaptureScreenCallback, OnUserCaptureScreenResult } from "../interface.uts" /** * 定义监听截屏事件工具类 */ class CaptureScreenTool { - static listener ?: UTSCallback; - static secureView ?: UIView; + static listener : UserCaptureScreenCallback | null; + static secureView : UIView | null; // 监听截屏 - static listenCaptureScreen(callback ?: UTSCallback) { + static listenCaptureScreen(callback : UserCaptureScreenCallback | null) { this.listener = callback - + // 注册监听截屏事件及回调方法 // target-action 回调方法需要通过 Selector("方法名") 构建 const method = Selector("userDidTakeScreenshot") @@ -25,35 +25,45 @@ class CaptureScreenTool { // 捕获截屏回调的方法 // target-action 的方法前需要添加 @objc 前缀 @objc static userDidTakeScreenshot() { - // 回调 - this.listener?.({}) + // 回调 + const res: OnUserCaptureScreenResult = { + errCode: 0, + errSubject: "uni-usercapturescreen", + errMsg: "onUserCaptureScreen: ok", + path: null + } + this.listener?.(res) } // 移除监听事件 - static removeListen(callback ?: UTSCallback) { + static removeListen(callback : UserCaptureScreenCallback | null) { this.listener = null - NotificationCenter.default.removeObserver(this) - callback?.({}) + NotificationCenter.default.removeObserver(this) + const res: OnUserCaptureScreenResult = { + errCode: 0, + errSubject: "uni-usercapturescreen", + errMsg: "offUserCaptureScreen: ok", + path: null + } + callback?.(res) } static createSecureView() : UIView | null { let field = new UITextField(frame = CGRect.zero) field.isSecureTextEntry = true - if (field.subviews.count > 0 && UIDevice.current.systemVersion != '15.1') { - let view = field.subviews.first - if (view != null) { - view!.subviews.forEach((item) => { - item.removeFromSuperview() - }) - view!.isUserInteractionEnabled = true - return view - } + 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 : SetUserCaptureScreenOption) { + static onAntiScreenshot(option : SetUserCaptureScreenOptions) { // uts方法默认会在子线程中执行,涉及 UI 操作必须在主线程中运行,通过 DispatchQueue.main.async 方法可将代码在主线程中运行 DispatchQueue.main.async(execute = () : void => { let secureView = this.createSecureView() @@ -70,18 +80,19 @@ class CaptureScreenTool { secureView!.frame = UIScreen.main.bounds rootView!.frame = rect } + } + let res: UserCaptureScreenResult = { + errCode: 0, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:ok" } - let res = new UserCaptureScreenResult() - res.errCode = 0; - res.errSubject = "uni-usercapturescreen"; - res.errMsg = "setUserCaptureScreen:ok"; option.success?.(res) option.complete?.(res) }) } // 关闭防截屏 - static offAntiScreenshot(option : SetUserCaptureScreenOption) { + static offAntiScreenshot(option : SetUserCaptureScreenOptions) { DispatchQueue.main.async(execute = () : void => { if (this.secureView != null) { let window = UTSiOS.getKeyWindow() @@ -94,11 +105,12 @@ class CaptureScreenTool { } } this.secureView = null + } + let res: UserCaptureScreenResult = { + errCode: 0, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:ok" } - let res = new UserCaptureScreenResult() - res.errCode = 0; - res.errSubject = "uni-usercapturescreen"; - res.errMsg = "setUserCaptureScreen:ok"; option.success?.(res) option.complete?.(res) }) @@ -108,34 +120,36 @@ class CaptureScreenTool { /** * 开启截图监听 */ -export const onUserCaptureScreen : OnUserCaptureScreen = function (callback ?: UTSCallback) { +export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { CaptureScreenTool.listenCaptureScreen(callback) } /** * 关闭截屏监听 */ -export const offUserCaptureScreen : OffUserCaptureScreen = function (callback ?: UTSCallback) { +export const offUserCaptureScreen : OffUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) { CaptureScreenTool.removeListen(callback) } /** * 开启/关闭防截屏 */ -export const setUserCaptureScreen : SetUserCaptureScreen = function (options : SetUserCaptureScreenOption) { - if (UIDevice.current.systemVersion < "13.0") { - let res = new UserCaptureScreenResult() - res.errCode = 12001; - res.errSubject = "uni-usercapturescreen"; - res.errMsg = "setUserCaptureScreen:system not support"; +export const setUserCaptureScreen : SetUserCaptureScreen = function (options : SetUserCaptureScreenOptions) { + if (UIDevice.current.systemVersion < "13.0") { + let res: UserCaptureScreenResult = { + errCode: 12001, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:system not support" + } options.fail?.(res); options.complete?.(res); - } else if (UIDevice.current.systemVersion == "15.1") { - let res = new UserCaptureScreenResult() - res.errCode = 12010; - res.errSubject = "uni-usercapturescreen"; - res.errMsg = "setUserCaptureScreen:system internal error"; + } else if (UIDevice.current.systemVersion == "15.1") { + let res: UserCaptureScreenResult = { + errCode: 12010, + errSubject: "uni-usercapturescreen", + errMsg: "setUserCaptureScreen:system internal error" + } options.fail?.(res); options.complete?.(res); } else { diff --git a/uni_modules/uni-usercapturescreen/utssdk/interface.uts b/uni_modules/uni-usercapturescreen/utssdk/interface.uts index 64b72e22e582c59ce92d85f89aff303b248af0b7..d5d744bea085e95b75a952fbbc547d7d5ab25d5f 100644 --- a/uni_modules/uni-usercapturescreen/utssdk/interface.uts +++ b/uni_modules/uni-usercapturescreen/utssdk/interface.uts @@ -2,6 +2,7 @@ export type UserCaptureScreenResult = { /** * 错误码 * 0:成功 + * -1:permission denied * 12001:system not support * 12010:system internal error */ @@ -16,7 +17,28 @@ export type UserCaptureScreenResult = { errMsg : string, } -export type SetUserCaptureScreenOption = { +export type OnUserCaptureScreenResult = { + /** + * 错误码 + * 0:成功 + * -1:permission denied(仅Android返回) + */ + errCode : number, + /** + * 调用API的名称 + */ + errSubject : string, + /** + * 错误的详细信息 + */ + errMsg : string, + /** + * 截屏文件路径(仅Android返回) + */ + path : string | null +} + +export type SetUserCaptureScreenOptions = { /** * true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容 */ @@ -35,35 +57,37 @@ export type SetUserCaptureScreenOption = { complete ?: (res : UserCaptureScreenResult) => void } +export type UserCaptureScreenCallback = (res : OnUserCaptureScreenResult) => void + /** * 开启截屏监听 * - * @param {UTSCallback} callback + * @param {UserCaptureScreenCallback} callback * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen * @platforms APP-IOS = ^9.0,APP-ANDROID = ^22 * @since 3.6.8 */ -export type OnUserCaptureScreen = (callback ?: UTSCallback) => void +export type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void /** * 关闭截屏监听 * - * @param {UTSCallback} callback + * @param {UserCaptureScreenCallback} callback * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen * @platforms APP-IOS = ^9.0,APP-ANDROID = ^22 * @since 3.6.8 */ -export type OffUserCaptureScreen = (callback ?: UTSCallback) => void +export type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void /** * 设置防截屏 * - * @param {SetUserCaptureScreenOption} options + * @param {SetUserCaptureScreenOptions} options * @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen * @platforms APP-IOS = ^9.0,APP-ANDROID = ^22 * @since 3.7.3 */ -export type SetUserCaptureScreen = (options : SetUserCaptureScreenOption) => void +export type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void interface uni { onUserCaptureScreen : OnUserCaptureScreen,