index.uts 4.4 KB
Newer Older
1 2 3


import {
4 5
	UTSAndroid
} from "io.dcloud.uts";
6 7 8 9 10 11 12 13 14 15


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';
16
import WindowManager from 'android.view.WindowManager';
17
import { SetUserCaptureScreenOption, UserCaptureScreenResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen } from "../interface.uts";
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39



/**
 * 文件监听器
 */
let screenOB: ScreenFileObserver | null = null;
/**
 * 记录文件监听器上次监听的时间戳,避免重复监听
 */
let lastFileObserverTime: number = 0;
/**
 * 图片被捕获的实现
 */
let imageChange: UTSCallback | null = null;




/**
 * android 文件监听实现
 */
40
@Suppress("DEPRECATION")
41 42 43 44 45 46 47 48 49
class ScreenFileObserver extends FileObserver {

	/**
	 * 所有截屏文件的存放目录
	 */
	allScreen: File;

	
	constructor(screenFile: string) {
杜庆泉's avatar
杜庆泉 已提交
50
		super(new File(screenFile))
51
		this.allScreen = new File(screenFile);
打打卡夫卡's avatar
打打卡夫卡 已提交
52
		
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
	}


	override onEvent(event: Int, path?: string): 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 = {
杜庆泉's avatar
杜庆泉 已提交
71
				errCode:1,
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
				image:newPath
			}
			
			imageChange!(ret);
		}
	}
}








/**
 * 开启截图监听
 */
90
@Suppress("DEPRECATION")
DCloud-yyl's avatar
DCloud-yyl 已提交
91
export const onUserCaptureScreen : OnUserCaptureScreen = function (callback ?: UTSCallback) {
92 93
	
	// 检查相关权限是否已经具备
94
	if (ActivityCompat.checkSelfPermission(UTSAndroid.getUniActivity()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
95
		// 不具备权限,申请权限,并且告知用户监听失败
96
		ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001)
97 98 99
		
		// 因权限缺失导致监听失败
		let ret = {
杜庆泉's avatar
杜庆泉 已提交
100
			errCode:-1
101
		}
DCloud-yyl's avatar
DCloud-yyl 已提交
102
		callback?.(ret);
103 104 105 106 107 108 109 110 111 112
		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);
	
杜庆泉's avatar
杜庆泉 已提交
113
	if (Build.MANUFACTURER.toLowerCase() === "xiaomi") {
114 115 116 117 118 119 120 121 122
		directory_screenshot = new File(directory_dcim, "Screenshots");
	} else {
		directory_screenshot = new File(directory_pictures, "Screenshots");
	}
	
	if (screenOB != null) {
		screenOB!.stopWatching()
	}
	//开始监听
DCloud-yyl's avatar
DCloud-yyl 已提交
123
	screenOB = new ScreenFileObserver(directory_screenshot.getPath())
124 125 126 127
	screenOB!.startWatching()

	// 监听成功
	let ret = {
杜庆泉's avatar
杜庆泉 已提交
128
		errCode:0
129
	}
DCloud-yyl's avatar
DCloud-yyl 已提交
130
	callback?.(ret);
131 132 133 134 135 136 137
	
}


/**
 * 关闭截屏监听
 */
DCloud-yyl's avatar
DCloud-yyl 已提交
138
export const offUserCaptureScreen : OffUserCaptureScreen = function (callback ?: UTSCallback) {
139 140 141 142 143 144 145 146

	// android 10以上,关闭监听通过移除文件监听器实现
	if (screenOB != null) {
		screenOB!.stopWatching()
		screenOB = null
	}
	lastFileObserverTime = 0;
	
DCloud-yyl's avatar
DCloud-yyl 已提交
147
	callback?.({});
148 149
}

150 151 152
/**
 * 设置是否禁止截屏
 */
153 154
export const setUserCaptureScreen : SetUserCaptureScreen = function (option: SetUserCaptureScreenOption) {
	// 切换到UI线程
155
	UTSAndroid.getUniActivity()?.runOnUiThread(new SetUserCaptureScreenRunnable(option.enable));
156 157 158 159
	const res = new UserCaptureScreenResult();
	res.errCode = 0;
	res.errMsg = "setUserCaptureScreen:ok";
	res.errSubject = "uni-setUserCaptureScreen";
160 161 162 163 164 165 166
	option.success?.(res);
	option.complete?.(res);
}

class SetUserCaptureScreenRunnable extends Runnable {
	
	/**
167 168
	 * ture: 允许用户截屏
	 * false: 不允许用户截屏,防止用户截屏到应用页面内容
169
	 */
170
	private enable: boolean;
171

172
	constructor(enable: boolean) {
173
		super();
174
		this.enable = enable;
175 176 177
	}

	override run(): void {
178
		if (this.enable) {
179
			UTSAndroid.getUniActivity()?.getWindow()?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
180 181
		} else {
			UTSAndroid.getUniActivity()?.getWindow()?.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
182 183 184 185
		}
	}
}

186 187