提交 c1ef0e94 编写于 作者: dcloud_wdl's avatar dcloud_wdl

Merge remote-tracking branch 'origin/alpha'

{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ {
// launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
"version": "0.0", "version" : "0.0",
"configurations": [{ "configurations" : [
"app-plus" :
{ {
"app-plus" : {
"launchtype" : "local" "launchtype" : "local"
}, },
"default" : "default" : {
{
"launchtype" : "local" "launchtype" : "local"
}, },
"type" : "uniCloud" "type" : "uniCloud"
},
{
"bundleId" : "io.dcloud.test123456",
"certificateFile" : "/Users/lizhongyi/Desktop/文件/证书/dev_123.p12",
"certificateProfileFile" : "/Users/lizhongyi/Desktop/文件/证书/io_dcloud_test123456.mobileprovision",
"type" : "uni-app:app-ios"
} }
] ]
} }
{ {
"name" : "uni-api", "name": "uni-api",
"appid" : "__UNI__4F60974", "appid": "__UNI__ED9218B",
"description" : "", "description": "",
"versionName" : "1.0.0", "versionName": "1.0.0",
"versionCode" : "100", "versionCode": "100",
"transformPx" : false, "transformPx": false,
/* 5+App特有相关 */ /* 5+App特有相关 */
"app-plus" : { "app-plus": {
"usingComponents" : true, "usingComponents": true,
"nvueStyleCompiler" : "uni-app", "nvueStyleCompiler": "uni-app",
"compilerVersion" : 3, "compilerVersion": 3,
"splashscreen" : { "splashscreen": {
"alwaysShowBeforeRender" : true, "alwaysShowBeforeRender": true,
"waiting" : true, "waiting": true,
"autoclose" : true, "autoclose": true,
"delay" : 0 "delay": 0
}, },
/* 模块配置 */ /* 模块配置 */
"modules" : {}, "modules": {},
/* 应用发布信息 */ /* 应用发布信息 */
"distribute" : { "distribute": {
/* android打包配置 */ /* android打包配置 */
"android" : { "android": {
"permissions" : [ "permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
...@@ -41,32 +41,32 @@ ...@@ -41,32 +41,32 @@
] ]
}, },
/* ios打包配置 */ /* ios打包配置 */
"ios" : {}, "ios": {},
/* SDK配置 */ /* SDK配置 */
"sdkConfigs" : {} "sdkConfigs": {}
} }
}, },
/* 快应用特有相关 */ /* 快应用特有相关 */
"quickapp" : {}, "quickapp": {},
/* 小程序特有相关 */ /* 小程序特有相关 */
"mp-weixin" : { "mp-weixin": {
"appid" : "", "appid": "",
"setting" : { "setting": {
"urlCheck" : false "urlCheck": false
}, },
"usingComponents" : true "usingComponents": true
}, },
"mp-alipay" : { "mp-alipay": {
"usingComponents" : true "usingComponents": true
}, },
"mp-baidu" : { "mp-baidu": {
"usingComponents" : true "usingComponents": true
}, },
"mp-toutiao" : { "mp-toutiao": {
"usingComponents" : true "usingComponents": true
}, },
"uniStatistics" : { "uniStatistics": {
"enable" : false "enable": false
}, },
"vueVersion" : "2" "vueVersion": "2"
} }
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
</view> </view>
<button @tap="testScreenShotListen">开启截屏监听</button> <button @tap="testScreenShotListen">开启截屏监听</button>
<button @tap="testScreenShotOff">关闭截屏监听</button> <button @tap="testScreenShotOff">关闭截屏监听</button>
<button @tap="testSetUserCaptureScreen">{{setUserCaptureScreenText}}</button>
<button @tap="testGetBatteryInfo">获取电池电量</button> <button @tap="testGetBatteryInfo">获取电池电量</button>
<button @tap="testonMemoryWarning">开启内存不足告警监听</button> <button @tap="testonMemoryWarning">开启内存不足告警监听</button>
<button @tap="testoffMemoryWarning">关闭内存不足告警监听</button> <button @tap="testoffMemoryWarning">关闭内存不足告警监听</button>
...@@ -25,6 +27,9 @@ ...@@ -25,6 +27,9 @@
return { return {
title: 'Hello', title: 'Hello',
memListener:null, memListener:null,
setUserCaptureScreenFlag: false,
setUserCaptureScreenText: '禁止截屏',
permissionGranted: false
} }
}, },
onLoad() { onLoad() {
...@@ -133,35 +138,14 @@ ...@@ -133,35 +138,14 @@
var that = this; var that = this;
uni.onUserCaptureScreen(function(res) { uni.onUserCaptureScreen(function(res) {
console.log(res); console.log(res);
if (uni.getSystemInfoSync().platform == "android") {
// 除android 之外的平台,不需要判断返回状态码
if(res.errCode == -1){
// 启动失败
return ;
}else if(res.errCode == 0){
uni.showToast({
icon:"none",
title:'截屏监听已开启'
})
}else {
uni.showToast({
icon:"none",
title:'捕获截屏事件'
})
that.screenImage = res.image
}
}else{
// 除android 之外的平台,不需要判断返回状态码
uni.showToast({ uni.showToast({
icon:"none", icon:"none",
title:'捕获截屏事件' title:'捕获截屏事件'
}) })
} that.screenImage = res.path
}); });
if (uni.getSystemInfoSync().platform != "android") { if (uni.getSystemInfoSync().platform != "android" || that.permissionGranted) {
// 除android 之外的平台,直接提示监听已开启 // 除android 之外的平台,直接提示监听已开启
uni.showToast({ uni.showToast({
icon:"none", icon:"none",
...@@ -190,6 +174,31 @@ ...@@ -190,6 +174,31 @@
} }
}) })
}, },
testSetUserCaptureScreen() {
let flag = this.setUserCaptureScreenFlag;
uni.setUserCaptureScreen({
enable: flag,
success: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " success: " + JSON.stringify(res));
},
fail: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " fail: " + JSON.stringify(res));
},
complete: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " complete: " + JSON.stringify(res));
}
});
uni.showToast({
icon:"none",
title: this.setUserCaptureScreenText
});
this.setUserCaptureScreenFlag = !this.setUserCaptureScreenFlag;
if (this.setUserCaptureScreenFlag) {
this.setUserCaptureScreenText = '允许截屏';
} else {
this.setUserCaptureScreenText = '禁止截屏';
}
},
} }
} }
</script> </script>
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
}, },
"uni_modules": { "uni_modules": {
"uni-ext-api": { "uni-ext-api": {
"uni": "getBatteryInfo" "uni": ["getBatteryInfo"]
}, },
"dependencies": [], "dependencies": [],
"encrypt": [], "encrypt": [],
......
...@@ -2,14 +2,9 @@ import Context from "android.content.Context"; ...@@ -2,14 +2,9 @@ import Context from "android.content.Context";
import BatteryManager from "android.os.BatteryManager"; import BatteryManager from "android.os.BatteryManager";
import { UTSAndroid } from "io.dcloud.uts"; import { UTSAndroid } from "io.dcloud.uts";
import { GetBatteryInfo, GetBatteryInfoSuccess, GetBatteryInfoFail, GetBatteryInfoOptions } from '../interface.uts'
type GetBatteryInfoOptions = { export const getBatteryInfo : GetBatteryInfo = function (options) {
success?: (res: UTSJSONObject) => void
fail?: (res: UTSJSONObject) => void
complete?: (res: UTSJSONObject) => void
}
export default function getBatteryInfo(options: GetBatteryInfoOptions) {
const context = UTSAndroid.getAppContext(); const context = UTSAndroid.getAppContext();
if (context != null) { if (context != null) {
const manager = context.getSystemService( const manager = context.getSystemService(
...@@ -18,9 +13,7 @@ export default function getBatteryInfo(options: GetBatteryInfoOptions) { ...@@ -18,9 +13,7 @@ export default function getBatteryInfo(options: GetBatteryInfoOptions) {
const level = manager.getIntProperty( const level = manager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY BatteryManager.BATTERY_PROPERTY_CAPACITY
); );
const res = { const res : GetBatteryInfoSuccess = {
errCode: 0,
errSubject: "uni-getBatteryInfo",
errMsg: 'getBatteryInfo:ok', errMsg: 'getBatteryInfo:ok',
level, level,
isCharging: manager.isCharging() isCharging: manager.isCharging()
...@@ -28,10 +21,11 @@ export default function getBatteryInfo(options: GetBatteryInfoOptions) { ...@@ -28,10 +21,11 @@ export default function getBatteryInfo(options: GetBatteryInfoOptions) {
options.success?.(res) options.success?.(res)
options.complete?.(res) options.complete?.(res)
} else { } else {
const res = { const res : GetBatteryInfoFail = {
errSubject: "uni-getBatteryInfo", errSubject: "uni-getBatteryInfo",
errCode: 1001, errCode: 1001,
errMsg: 'getBatteryInfo:fail getAppContext is null' errMsg: 'getBatteryInfo:fail getAppContext is null',
cause: null
} }
options.fail?.(res) options.fail?.(res)
options.complete?.(res) options.complete?.(res)
......
...@@ -2,27 +2,18 @@ ...@@ -2,27 +2,18 @@
import { UIDevice } from "UIKit"; import { UIDevice } from "UIKit";
import { Int } from 'Swift'; import { Int } from 'Swift';
/** import { GetBatteryInfo, GetBatteryInfoSuccess } from '../interface.uts';
* 定义 接口参数
*/
type GetBatteryInfoOptions = {
success?: (res: object) => void;
fail?: (res: object) => void;
complete?: (res: object) => void;
};
/** /**
* 导出 获取电量方法 * 导出 获取电量方法
*/ */
export default function getBatteryInfo(options: GetBatteryInfoOptions) { export const getBatteryInfo : GetBatteryInfo = function (options) {
// 开启电量检测 // 开启电量检测
UIDevice.current.isBatteryMonitoringEnabled = true UIDevice.current.isBatteryMonitoringEnabled = true
// 返回数据 // 返回数据
const res = { const res : GetBatteryInfoSuccess = {
errCode: 0,
errSubject: "uni-getBatteryInfo",
errMsg: "getBatteryInfo:ok", errMsg: "getBatteryInfo:ok",
level: new Int(UIDevice.current.batteryLevel * 100), level: new Int(UIDevice.current.batteryLevel * 100),
isCharging: UIDevice.current.batteryState == UIDevice.BatteryState.charging, isCharging: UIDevice.current.batteryState == UIDevice.BatteryState.charging,
......
type GetBatteryInfoResult = { export type GetBatteryInfoSuccess = {
/** errMsg : string,
* 错误码
*/
errCode: number,
/**
* 调用API的名称
*/
errSubject: string,
/**
* 错误的详细信息
*/
errMsg: string,
/** /**
* 设备电量,范围1 - 100 * 设备电量,范围1 - 100
*/ */
level: number, level : number,
/** /**
* 是否正在充电中 * 是否正在充电中
*/ */
isCharging: boolean isCharging : boolean
} }
interface UniError<T> { export type GetBatteryInfoFail = {
/** /**
* 错误码 * 错误码
*/ */
errCode:T, errCode : number,
/** /**
* 调用API的名称 * 调用API的名称
*/ */
errSubject:string, errSubject : string,
/** /**
* 错误的详细信息 * 错误的详细信息
*/ */
errMsg:string, errMsg : string,
/** /**
* 错误来源 * 错误来源
*/ */
cause:any cause : any | null
} }
/**
* 错误码
*/
type GetBatteryInfoErrorCode =
/** 成功 */
0
/** getAppContext is null */
| 1001
/** navigator.getBattery is unsupported */
| 1002
;
export type GetBatteryInfoOptions = { export type GetBatteryInfoOptions = {
/** /**
* 接口调用结束的回调函数(调用成功、失败都会执行) * 接口调用结束的回调函数(调用成功、失败都会执行)
*/ */
success?: (res: GetBatteryInfoResult) => void success ?: (res : GetBatteryInfoSuccess) => void
/** /**
* 接口调用失败的回调函数 * 接口调用失败的回调函数
*/ */
fail?: (res: UniError<GetBatteryInfoErrorCode>) => void fail ?: (res : GetBatteryInfoFail) => void
/** /**
* 接口调用成功的回调 * 接口调用成功的回调
*/ */
complete?: (res: object) => void complete ?: (res : any) => void
} }
/** /**
* 获取电量信息 * 获取电量信息
* @param {GetBatteryInfoOptions} options * @param {GetBatteryInfoOptions} options
* *
* *
* @tutorial https://uniapp.dcloud.net.cn/api/system/batteryInfo.html * @tutorial https://uniapp.dcloud.net.cn/api/system/batteryInfo.html
* @platforms APP-IOS = ^9.0,APP-ANDROID = ^22 * @platforms APP-IOS = ^9.0,APP-ANDROID = ^22
* @since 3.6.11 * @since 3.6.11
* *
* @assert () => success({errCode: 0, errSubject: "uni-getBatteryInfo", errMsg: "getBatteryInfo:ok", level: 60, isCharging: false }) * @assert () => success({errCode: 0, errSubject: "uni-getBatteryInfo", errMsg: "getBatteryInfo:ok", level: 60, isCharging: false })
* @assert () => fail({errCode: 1001, errSubject: "uni-getBatteryInfo", errMsg: "getBatteryInfo:fail getAppContext is null" }) * @assert () => fail({errCode: 1001, errSubject: "uni-getBatteryInfo", errMsg: "getBatteryInfo:fail getAppContext is null" })
*/ */
export default function getBatteryInfo(options: GetBatteryInfoOptions): void export type GetBatteryInfo = (options : GetBatteryInfoOptions) => void
\ No newline at end of file
export default function getBatteryInfo(options) { export function getBatteryInfo(options) {
return my.getBatteryInfo(options) return my.getBatteryInfo(options)
} }
export default function getBatteryInfo(options) { export function getBatteryInfo(options) {
return swan.getBatteryInfo(options) return swan.getBatteryInfo(options)
} }
export default function getBatteryInfo(options) { export function getBatteryInfo(options) {
return qq.getBatteryInfo(options) return qq.getBatteryInfo(options)
} }
export default function getBatteryInfo(options) { export function getBatteryInfo(options) {
return wx.getBatteryInfo(options) return wx.getBatteryInfo(options)
} }
export default function getBatteryInfo(options) { export function getBatteryInfo(options) {
if (navigator.getBattery) { if (navigator.getBattery) {
navigator.getBattery().then(battery => { navigator.getBattery().then(battery => {
const res = { const res = {
......
import { UTSAndroid } from "io.dcloud.uts" import { UTSAndroid } from "io.dcloud.uts"
let listeners: UTSCallback[] = [] let listeners: UTSCallback[] = []
const onAppTrimMemoryListener = (res: number) => { const onAppTrimMemoryListener = (ret: number) => {
listeners.forEach(listener => { listeners.forEach(listener => {
let res = {
level:ret
}
listener(res) listener(res)
}) })
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
export function onMemoryWarning(callback: (res: number) => void) { export function onMemoryWarning(callback: UTSCallback) {
if (listeners.length == 0) { if (listeners.length == 0) {
// 仅首次执行底层的实际监听 // 仅首次执行底层的实际监听
UTSAndroid.onAppTrimMemory(onAppTrimMemoryListener) UTSAndroid.onAppTrimMemory(onAppTrimMemoryListener)
...@@ -22,8 +26,9 @@ export function onMemoryWarning(callback: (res: number) => void) { ...@@ -22,8 +26,9 @@ export function onMemoryWarning(callback: (res: number) => void) {
listeners.push(callback) listeners.push(callback)
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
export function offMemoryWarning(callback: UTSCallback | null = null) { export function offMemoryWarning(callback: UTSCallback | null) {
if(callback == null){ if(callback == null){
// 清除全部回调 // 清除全部回调
...@@ -42,3 +47,4 @@ export function offMemoryWarning(callback: UTSCallback | null = null) { ...@@ -42,3 +47,4 @@ export function offMemoryWarning(callback: UTSCallback | null = null) {
UTSAndroid.offAppTrimMemory(onAppTrimMemoryListener) UTSAndroid.offAppTrimMemory(onAppTrimMemoryListener)
} }
} }
...@@ -34,7 +34,8 @@ ...@@ -34,7 +34,8 @@
"uni-ext-api":{ "uni-ext-api":{
"uni": { "uni": {
"onUserCaptureScreen": "onUserCaptureScreen", "onUserCaptureScreen": "onUserCaptureScreen",
"offUserCaptureScreen": "offUserCaptureScreen" "offUserCaptureScreen": "offUserCaptureScreen",
"setUserCaptureScreen": "setUserCaptureScreen"
} }
}, },
"dependencies": [], "dependencies": [],
......
import { UTSAndroid } from "io.dcloud.uts";
import {
UTSAndroid
} from "io.dcloud.uts";
import ActivityCompat from "androidx.core.app.ActivityCompat"; import ActivityCompat from "androidx.core.app.ActivityCompat";
import Manifest from "android.Manifest"; import Manifest from "android.Manifest";
import PackageManager from "android.content.pm.PackageManager"; import PackageManager from "android.content.pm.PackageManager";
...@@ -13,137 +7,133 @@ import FileObserver from "android.os.FileObserver"; ...@@ -13,137 +7,133 @@ import FileObserver from "android.os.FileObserver";
import File from "java.io.File"; import File from "java.io.File";
import Environment from "android.os.Environment"; import Environment from "android.os.Environment";
import System from 'java.lang.System'; import System from 'java.lang.System';
import WindowManager from 'android.view.WindowManager';
import { OnUserCaptureScreenCallbackResult, UserCaptureScreenCallback, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreenSuccess, SetUserCaptureScreenOptions, 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 文件监听实现 * android 文件监听实现
*/ */
@Suppress("DEPRECATION")
class ScreenFileObserver extends FileObserver { 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 | null) : void {
override onEvent(event: Int, path?: string): void {
// 只监听文件新增事件 // 只监听文件新增事件
if (event == FileObserver.CREATE) { if (event == FileObserver.CREATE) {
if (path != null) {
let newPath: string = new File(this.allScreen, path!).getPath(); const currentTime = System.currentTimeMillis();
let currentTime = System.currentTimeMillis(); if ((currentTime - lastObserverTime) < 1000) {
// 本地截屏行为比上一次超过1000ms, 才认为是一个有效的时间
if ((currentTime - lastFileObserverTime) < 1000) {
// 本地截屏行为比上一次超过1000ms,才认为是一个有效的时间
return; return;
} }
lastObserverTime = currentTime;
lastFileObserverTime = System.currentTimeMillis() const screenShotPath = new File(this.screenFile, path).getPath();
let ret = { const res : OnUserCaptureScreenCallbackResult = {
errCode:1, path: screenShotPath
image:newPath }
listener?.(res);
} }
imageChange!(ret);
} }
} }
} }
/** /**
* 开启截图监听 * 开启截图监听
*/ */
@Suppress("DEPRECATION") export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
export function onUserCaptureScreen(callback: (res:UTSJSONObject) => void) { // 检查相关权限是否已授予
if (ActivityCompat.checkSelfPermission(UTSAndroid.getAppContext()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 检查相关权限是否已经具备 // 无权限,申请权限
if (ActivityCompat.checkSelfPermission(UTSAndroid.getUniActivity()!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001);
// 不具备权限,申请权限,并且告知用户监听失败 return;
ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1001)
// 因权限缺失导致监听失败
let ret = {
errCode:-1
}
callback(ret);
return ;
} }
// 更新监听
listener = callback;
imageChange = callback; let directory_screenshot : File;
if (Build.MANUFACTURER.toLowerCase() == "xiaomi") {
let directory_screenshot: File; // @Suppress("DEPRECATION")
// 找到设备存放截屏文件的目录 directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM), "Screenshots");
let directory_pictures = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES);
let directory_dcim = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DCIM);
if (Build.MANUFACTURER.toLowerCase() === "xiaomi") {
directory_screenshot = new File(directory_dcim, "Screenshots");
} else { } else {
directory_screenshot = new File(directory_pictures, "Screenshots"); // @Suppress("DEPRECATION")
directory_screenshot = new File(new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_PICTURES), "Screenshots");
} }
// 先结束监听 再开启监听
observer?.stopWatching();
observer = new ScreenFileObserver(directory_screenshot);
observer?.startWatching();
if (screenOB != null) {
screenOB!.stopWatching()
}
//开始监听
screenOB = new ScreenFileObserver(directory_screenshot.path)
screenOB!.startWatching()
// 监听成功 UTSAndroid.onAppActivityDestroy(function(){
let ret = { observer?.stopWatching()
errCode:0 observer = null
} })
callback(ret);
}
}
/** /**
* 关闭截屏监听 * 关闭截屏监听
*/ */
export function offUserCaptureScreen(success: (res: any) => void) { export const offUserCaptureScreen : OffUserCaptureScreen = function (_ : UserCaptureScreenCallback | null) {
// android10以上,关闭监听通过移除文件监听器实现
// android 10以上,关闭监听通过移除文件监听器实现 observer?.stopWatching();
if (screenOB != null) { observer = null;
screenOB!.stopWatching() lastObserverTime = 0;
screenOB = null }
}
lastFileObserverTime = 0;
success({}); /**
* 设置是否禁止截屏
*/
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);
}
}
}
import { NotificationCenter } from 'Foundation'; import { NotificationCenter } from 'Foundation';
import { UIApplication } from "UIKit" import { CGRect } from "CoreFoundation";
import { Selector } from "ObjectiveC" import { UIApplication, UIView, UITextField, UIScreen, UIDevice } from "UIKit"
import { UTSiOS } from "DCloudUTSFoundation"
import { DispatchQueue } from 'Dispatch';
import { SetUserCaptureScreenOptions, OnUserCaptureScreenCallbackResult, OnUserCaptureScreen, OffUserCaptureScreen, SetUserCaptureScreen, UserCaptureScreenCallback, SetUserCaptureScreenSuccess, SetUserCaptureScreenFail } from "../interface.uts"
/** /**
* 定义监听截屏事件工具类 * 定义监听截屏事件工具类
*/ */
class CaptureScreenTool { class CaptureScreenTool {
static listener: UTSCallback | null; static listener : UserCaptureScreenCallback | null;
static secureView : UIView | null;
// 监听截屏 // 监听截屏
static listenCaptureScreen(callback: UTSCallback | null) { static listenCaptureScreen(callback : UserCaptureScreenCallback | null) {
this.listener = callback this.listener = callback
// 注册监听截屏通知事件及设置回调方法 // 注册监听截屏事件及回调方法
// target-action 回调方法需要通过 Selector("方法名") 构建 // target-action 回调方法需要通过 Selector("方法名") 构建
const method = Selector("userDidTakeScreenshot") const method = Selector("userDidTakeScreenshot")
NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.userDidTakeScreenshotNotification, object = null) NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.userDidTakeScreenshotNotification, object = null)
...@@ -21,28 +25,122 @@ class CaptureScreenTool { ...@@ -21,28 +25,122 @@ class CaptureScreenTool {
// 捕获截屏回调的方法 // 捕获截屏回调的方法
// target-action 的方法前需要添加 @objc 前缀 // target-action 的方法前需要添加 @objc 前缀
@objc static userDidTakeScreenshot() { @objc static userDidTakeScreenshot() {
// 触发回调 // 回调
this.listener?.({}) const res: OnUserCaptureScreenCallbackResult = {
}
this.listener?.(res)
} }
// 移除监听事件 // 移除监听事件
static removeListen(callback: UTSCallback | null) { static removeListen(callback : UserCaptureScreenCallback | null) {
this.listener = null this.listener = null
NotificationCenter.default.removeObserver(this) NotificationCenter.default.removeObserver(this)
callback?.({}) }
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 function onUserCaptureScreen(callback: UTSCallback | null) { export const onUserCaptureScreen : OnUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
CaptureScreenTool.listenCaptureScreen(callback) CaptureScreenTool.listenCaptureScreen(callback)
} }
/** /**
* 关闭截屏监听 * 关闭截屏监听
*/ */
export function offUserCaptureScreen(callback: UTSCallback | null) { export const offUserCaptureScreen : OffUserCaptureScreen = function (callback : UserCaptureScreenCallback | null) {
CaptureScreenTool.removeListen(callback) CaptureScreenTool.removeListen(callback)
} }
/**
* 开启/关闭防截屏
*/
export const setUserCaptureScreen : SetUserCaptureScreen = function (options : SetUserCaptureScreenOptions) {
if (UIDevice.current.systemVersion < "13.0") {
let res: SetUserCaptureScreenFail = {
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: SetUserCaptureScreenFail = {
errCode: 12010,
errSubject: "uni-usercapturescreen",
errMsg: "setUserCaptureScreen:system internal error"
}
options.fail?.(res);
options.complete?.(res);
} else {
if (options.enable == true) {
CaptureScreenTool.offAntiScreenshot(options)
} else {
CaptureScreenTool.onAntiScreenshot(options)
}
}
}
/**
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数
*/
export type OnUserCaptureScreenCallbackResult = {
/**
* 截屏文件路径(仅Android返回)
*/
path ?: string
}
/**
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义
*/
export type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void
/**
* uni.onUserCaptureScreen函数定义
* 开启截屏监听
*
* @param {UserCaptureScreenCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen
* @platforms APP-IOS = ^9.0,APP-ANDROID = ^19
* @since 3.6.8
*/
export type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
/**
* uni.offUserCaptureScreen函数定义
* 关闭截屏监听
*
* @param {UserCaptureScreenCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen
* @platforms APP-IOS = ^9.0,APP-ANDROID = ^19
* @since 3.6.8
*/
export type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
/**
* uni.setUserCaptureScreen成功回调参数
*/
export type SetUserCaptureScreenSuccess = {
}
/**
* uni.setUserCaptureScreen失败回调参数
*/
export type SetUserCaptureScreenFail = {
/**
* 错误码
* 0:成功
* -1:permission denied
* 12001:system not support
* 12010:system internal error
*/
errCode : number,
/**
* 调用API的名称
*/
errSubject : string,
/**
* 错误的详细信息
*/
errMsg : string,
}
/**
* uni.setUserCaptureScreen成功回调函数定义
*/
export type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void
/**
* uni.setUserCaptureScreen失败回调函数定义
*/
export type SetUserCaptureScreenFailCallback = (res : SetUserCaptureScreenFail) => 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
}
/**
* * uni.setUserCaptureScreen函数定义
* 设置防截屏
*
* @param {SetUserCaptureScreenOptions} options
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen
* @platforms APP-IOS = ^13.0,APP-ANDROID = ^19
* @since 3.7.3
*/
export type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void
interface uni {
onUserCaptureScreen : OnUserCaptureScreen,
offUserCaptureScreen : OffUserCaptureScreen,
setUserCaptureScreen : SetUserCaptureScreen
}
\ No newline at end of file
...@@ -42,7 +42,7 @@ type GetConnectedWifiOptions = { ...@@ -42,7 +42,7 @@ type GetConnectedWifiOptions = {
*/ */
type WifiConnectOption = { type WifiConnectOption = {
SSID:string; SSID:string;
BSSID:string; BSSID?:string;
password:string; password:string;
maunal:boolean; maunal:boolean;
// 只返回ssid // 只返回ssid
......
...@@ -8,23 +8,23 @@ import { UIDevice } from 'UIKit'; ...@@ -8,23 +8,23 @@ import { UIDevice } from 'UIKit';
* Wifi 函数通用入参封装 * Wifi 函数通用入参封装
*/ */
type WifiOption = { type WifiOption = {
success?: (res: object) => void; success?: (res: UniWifiResult) => void;
fail?: (res: object) => void; fail?: (res: UniWifiResult) => void;
complete?: (res: object) => void; complete?: (res: UniWifiResult) => void;
}; };
/** /**
* Wifi 链接参数封装 * Wifi 链接参数封装
*/ */
type WifiConnectOption = { type WifiConnectOption = {
SSID: string; SSID?: string;
BSSID: string; BSSID?: string;
password: string; password?: string;
maunal: boolean; maunal?: boolean;
partialInfo: boolean; //ios不生效 partialInfo?: boolean; //ios不生效
success?: (res: object) => void; success?: (res: UniWifiResult) => void;
fail?: (res: object) => void; fail?: (res: UniWifiResult) => void;
complete?: (res: object) => void; complete?: (res: UniWifiResult) => void;
} }
/** /**
...@@ -32,9 +32,9 @@ type WifiConnectOption = { ...@@ -32,9 +32,9 @@ type WifiConnectOption = {
*/ */
type GetConnectedWifiOptions = { type GetConnectedWifiOptions = {
partialInfo?: boolean partialInfo?: boolean
success?: (res: UTSJSONObject) => void success?: (res: UniWifiResult) => void
fail?: (res: UTSJSONObject) => void fail?: (res: UniWifiResult) => void
complete?: (res: UTSJSONObject) => void complete?: (res: UniWifiResult) => void
} }
/* /*
...@@ -48,6 +48,15 @@ type UniWifiInfo = { ...@@ -48,6 +48,15 @@ type UniWifiInfo = {
frequency: number; frequency: number;
} }
type UniWifiResult = {
errCode : number,
errSubject : string,
errMsg : string,
wifi: UniWifiInfo | null
}
type UniWifiCallback = () => void
/* /*
* 系统定位权限获取类 * 系统定位权限获取类
...@@ -114,12 +123,13 @@ function requestLocationPromise(@escaping completion: (res: boolean)=>void) { ...@@ -114,12 +123,13 @@ function requestLocationPromise(@escaping completion: (res: boolean)=>void) {
*/ */
function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions) { function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions) {
let arr = CNCopySupportedInterfaces() let arr = CNCopySupportedInterfaces()
let wifiInfo = new UniWifiInfo() let wifiInfo: UniWifiInfo = {
wifiInfo.BSSID = "" BSSID: "",
wifiInfo.SSID = "" SSID: "",
wifiInfo.secure = false secure: false,
wifiInfo.signalStrength = 0 signalStrength: 0,
wifiInfo.frequency = 0 frequency: 0
}
if (arr != null) { if (arr != null) {
let list = arr! as NSArray let list = arr! as NSArray
...@@ -148,7 +158,7 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions) ...@@ -148,7 +158,7 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions)
} }
if (wifiInfo.BSSID.length > 0 && wifiInfo.SSID.length > 0) { if (wifiInfo.BSSID.length > 0 && wifiInfo.SSID.length > 0) {
let res = { let res: UniWifiResult = {
errSubject: "uni-getConnectedWifi", errSubject: "uni-getConnectedWifi",
errCode: 0, errCode: 0,
errMsg: "getConnectedWifi:ok", errMsg: "getConnectedWifi:ok",
...@@ -157,19 +167,21 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions) ...@@ -157,19 +167,21 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions)
option.success?.(res) option.success?.(res)
option.complete?.(res) option.complete?.(res)
}else { }else {
const res = { const res: UniWifiResult = {
errSubject: "uni-getConnectedWifi", errSubject: "uni-getConnectedWifi",
errCode: 12010, errCode: 12010,
errMsg: "getConnectedWifi:system internal error" errMsg: "getConnectedWifi:system internal error",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
} }
}else { }else {
const res = { const res: UniWifiResult = {
errSubject: "uni-getConnectedWifi", errSubject: "uni-getConnectedWifi",
errCode: 12010, errCode: 12010,
errMsg: "getConnectedWifi:system internal error" errMsg: "getConnectedWifi:system internal error",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -182,7 +194,7 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions) ...@@ -182,7 +194,7 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions)
* 保存全局数据信息 * 保存全局数据信息
*/ */
class UniWiFiModuleGloabInfo { class UniWiFiModuleGloabInfo {
static alreadyStartWifi: boolean static alreadyStartWifi: boolean = false
} }
/* =================================== 对外暴露的接口 ==============================================*/ /* =================================== 对外暴露的接口 ==============================================*/
...@@ -194,10 +206,11 @@ class UniWiFiModuleGloabInfo { ...@@ -194,10 +206,11 @@ class UniWiFiModuleGloabInfo {
*/ */
export function startWifi(option: WifiOption) { export function startWifi(option: WifiOption) {
UniWiFiModuleGloabInfo.alreadyStartWifi = true UniWiFiModuleGloabInfo.alreadyStartWifi = true
let res = { let res: UniWifiResult = {
errSubject: "uni-startWifi", errSubject: "uni-startWifi",
errCode: 0, errCode: 0,
errMsg: "startWifi:ok" errMsg: "startWifi:ok",
wifi: null
} }
option.success?.(res) option.success?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -209,10 +222,11 @@ export function startWifi(option: WifiOption) { ...@@ -209,10 +222,11 @@ export function startWifi(option: WifiOption) {
export function stopWifi(option: WifiOption) { export function stopWifi(option: WifiOption) {
UniWiFiModuleGloabInfo.alreadyStartWifi = false UniWiFiModuleGloabInfo.alreadyStartWifi = false
LocationPromiseService.promiseCompletionHandler = [] LocationPromiseService.promiseCompletionHandler = []
let res = { let res: UniWifiResult = {
errSubject: "uni-stopWifi", errSubject: "uni-stopWifi",
errCode: 0, errCode: 0,
errMsg: "stopWifi:ok" errMsg: "stopWifi:ok",
wifi: null
} }
option.success?.(res) option.success?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -222,10 +236,11 @@ export function stopWifi(option: WifiOption) { ...@@ -222,10 +236,11 @@ export function stopWifi(option: WifiOption) {
* 获取wifi列表, 在调用之前需要引导用户跳转到系统设置-WIFI设置页面,系统搜索周边wifi后app才能接收到回调 * 获取wifi列表, 在调用之前需要引导用户跳转到系统设置-WIFI设置页面,系统搜索周边wifi后app才能接收到回调
*/ */
export function getWifiList(option: WifiOption) { export function getWifiList(option: WifiOption) {
let res = { let res: UniWifiResult = {
errSubject: "uni-getWifiList", errSubject: "uni-getWifiList",
errCode: 12001, errCode: 12001,
errMsg: "getWifiList:system not support" errMsg: "getWifiList:system not support",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -234,14 +249,14 @@ export function getWifiList(option: WifiOption) { ...@@ -234,14 +249,14 @@ export function getWifiList(option: WifiOption) {
/* 获取wifi列表的回调 /* 获取wifi列表的回调
* note: 请在getWifiList方法的回调里调用该方法 * note: 请在getWifiList方法的回调里调用该方法
*/ */
export function onGetWifiList(callback: UTSCallback) { export function onGetWifiList(callback: UniWifiCallback) {
} }
/* /*
* 注销获取wifi列表的回调 * 注销获取wifi列表的回调
*/ */
export function offGetWifiList(callback: UTSCallback) { export function offGetWifiList(callback: UniWifiCallback) {
} }
...@@ -251,10 +266,11 @@ export function offGetWifiList(callback: UTSCallback) { ...@@ -251,10 +266,11 @@ export function offGetWifiList(callback: UTSCallback) {
*/ */
export function getConnectedWifi(option: GetConnectedWifiOptions) { export function getConnectedWifi(option: GetConnectedWifiOptions) {
if (UniWiFiModuleGloabInfo.alreadyStartWifi == false) { if (UniWiFiModuleGloabInfo.alreadyStartWifi == false) {
let res = { let res: UniWifiResult = {
errSubject: "uni-getConnectedWifi", errSubject: "uni-getConnectedWifi",
errCode: 12000, errCode: 12000,
errMsg: "getConnectedWifi:not init", errMsg: "getConnectedWifi:not init",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -264,10 +280,11 @@ export function getConnectedWifi(option: GetConnectedWifiOptions) { ...@@ -264,10 +280,11 @@ export function getConnectedWifi(option: GetConnectedWifiOptions) {
if (success == true) { if (success == true) {
fetchConnectedWifiWithLocationPromise(option) fetchConnectedWifiWithLocationPromise(option)
}else { }else {
let res = { let res: UniWifiResult = {
errSubject: "uni-getConnectedWifi", errSubject: "uni-getConnectedWifi",
errCode: 12007, errCode: 12007,
errMsg: "getConnectedWifi:user denied", errMsg: "getConnectedWifi:user denied",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -283,10 +300,11 @@ export function getConnectedWifi(option: GetConnectedWifiOptions) { ...@@ -283,10 +300,11 @@ export function getConnectedWifi(option: GetConnectedWifiOptions) {
* 连接wifi * 连接wifi
*/ */
export function connectWifi(option: WifiConnectOption) { export function connectWifi(option: WifiConnectOption) {
let res = { let res: UniWifiResult = {
errSubject: "uni-connectWifi", errSubject: "uni-connectWifi",
errCode: 12001, errCode: 12001,
errMsg: "connectWifi:system not support" errMsg: "connectWifi:system not support",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
...@@ -296,28 +314,28 @@ export function connectWifi(option: WifiConnectOption) { ...@@ -296,28 +314,28 @@ export function connectWifi(option: WifiConnectOption) {
/* /*
* 连上wifi事件的监听函数 * 连上wifi事件的监听函数
*/ */
export function onWifiConnected(callback: UTSCallback) { export function onWifiConnected(callback: UniWifiCallback) {
} }
/* /*
* 连上wifi事件的监听函数, wifiInfo仅包含ssid * 连上wifi事件的监听函数, wifiInfo仅包含ssid
*/ */
export function onWifiConnectedWithPartialInfo(callback: UTSCallback) { export function onWifiConnectedWithPartialInfo(callback: UniWifiCallback) {
} }
/* /*
* 移除连接上wifi的事件的监听函数,不传此参数则移除所有监听函数。 * 移除连接上wifi的事件的监听函数,不传此参数则移除所有监听函数。
*/ */
export function offWifiConnected(callback: UTSCallback | null) { export function offWifiConnected(callback: UniWifiCallback | null) {
} }
/* /*
* 移除连接上wifi的事件的监听函数,不传此参数则移除所有监听函数。 * 移除连接上wifi的事件的监听函数,不传此参数则移除所有监听函数。
*/ */
export function onOffWifiConnectedWithPartialInfo(callback: UTSCallback | null) { export function onOffWifiConnectedWithPartialInfo(callback: UniWifiCallback | null) {
} }
...@@ -325,10 +343,11 @@ export function onOffWifiConnectedWithPartialInfo(callback: UTSCallback | null) ...@@ -325,10 +343,11 @@ export function onOffWifiConnectedWithPartialInfo(callback: UTSCallback | null)
* 设置 wifiList 中 AP 的相关信息。在 onGetWifiList 回调后调用,iOS特有接口。 * 设置 wifiList 中 AP 的相关信息。在 onGetWifiList 回调后调用,iOS特有接口。
*/ */
export function setWifiList(option: WifiOption) { export function setWifiList(option: WifiOption) {
let res = { let res: UniWifiResult = {
errSubject: "uni-setWifiList", errSubject: "uni-setWifiList",
errCode: 12001, errCode: 12001,
errMsg: "setWifiList:system not support" errMsg: "setWifiList:system not support",
wifi: null
} }
option.fail?.(res) option.fail?.(res)
option.complete?.(res) option.complete?.(res)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册