/**
* @author Mr_老冷 QQ:1920712147
* @date 20210807
*/
/**
* @author Mr_老冷 QQ:1920712147
* @description laoleng类
*/
let g_ret = null
const laoleng = {
app: {},
arr: {},
String: {},
RndStr: {},
/**
*@description 键盘功能
*/
Key: {},
};
logw("laoleng.js插件加载成功,EC教学咨询,Mr_老冷QQ:1920712147")
logw("laoleng.js配套文档https://home.laoleng.top:3001/web/#/9?page_id=167");
laoleng.getVersion = function () {
return "1.0.4"
}
/**
* @author Mr_老冷 QQ:1920712147
* @description 查找节点并点击
* @param {S} selector 选择器
* @param {Boolean?} isClick 是否点击
* @param {Boolean?} pointer 是否指针点击
* @return {Boolean} true/false;全局jsonObj g_ret;
* @example
* findNode(text("aaa").id("bbb"),true)
*/
function findNode(selector, isClick, pointer) {
if (typeOf(selector) !== "S") {
logw("防SB提示,findNode,传参类型不对:" + selector)
return false;
}
g_ret = selector.getOneNodeInfo(0);
if (g_ret) {
if (isClick) {
if (pointer) {
g_ret.click();
sleep(random(500, 1000));
} else {
findClickEx(g_ret)
}
}
return true;
}
return false;
}
/**
* @author Mr_老冷 QQ:1920712147
* @description 查找可用父点击节点并无指针点击
* @param {NodeInfo?} node 全局node返回值
* @param {Boolean?} isNoClick 是否不点击
* @return {Boolean} true/false;
* @example
* findClickEx(g_ret)
*/
function findClickEx(node, isNoClick) {
let tmp_ret = false
node = node || g_ret
if (typeOf(node) !== "NodeInfo") {
logw("防SB提示,findClickEx,传参类型不对:" + node)
return false;
}
//4次找不到就算了
try {
for (let i = 0; i <= 3; i++) {
if (!node) return false
if (node.clickable) {
tmp_ret = !isNoClick ? node.clickEx() : node
!isNoClick && sleep(random(500, 1000));
return tmp_ret
}
node = node.parent()
}
} catch (e) {
loge(e);
}
return false
}
/**
* @description 查找可用父滚动节点并滚动
* @param {NodeInfo?} node 全局node返回值
* @param {Boolean?} isNoScroll 是否不滚动
* @return {Boolean} true/false;
* @example
*/
function findScrollableP(node, isNoScroll) {
let tmp_ret = false
node = node || g_ret
if (typeOf(node) !== "NodeInfo") {
logw("防SB提示,findClickEx,传参类型不对:" + node)
return false;
}
//11次找不到就算了
try {
for (let i = 0; i <= 10; i++) {
if (!node) return false
if (node.scrollable) {
tmp_ret = !isNoScroll ? node.scrollForward() : node
!isNoScroll && sleep(random(500, 1000));
return tmp_ret
}
node = node.parent()
}
} catch (e) {
loge(e);
}
return false
}
/**
* @description 获取节点x中心点
* @param node {NodeInfo?} 节点对象
* @returns {number}
*/
function centerX(node) {
node = node || g_ret
return (node.bounds.left + node.bounds.right) / 2
}
/**
* @description 获取节点y中心点
* @param node {NodeInfo?}节点对象
* @returns {number}
*/
function centerY(node) {
node = node || g_ret
return (node.bounds.top + node.bounds.bottom) / 2
}
/**
* @description 在节点一半的范围内随机按压
* @param node {NodeInfo?} 节点对象
* @param timeMin {number?} 最小时长,默认1s
* @param timeMax {number?} 最大时长,默认同最小
*/
function pressHalf(node, timeMin, timeMax) {
node = node || g_ret
timeMin = timeMin * 1000 || 1000
timeMax = timeMax * 1000 || timeMin
let x1 = ~~((node.bounds.right - node.bounds.left) / 4 + node.bounds.left)
let y1 = ~~((node.bounds.bottom - node.bounds.top) / 4 + node.bounds.top)
let x2 = ~~((node.bounds.right - node.bounds.left) / 4 * 3 + node.bounds.left)
let y2 = ~~((node.bounds.bottom - node.bounds.top) / 4 * 3 + node.bounds.top)
return press(random(x1, x2), random(y1, y2), random(timeMin, timeMax))
}
/**
* @description 判断数据类型
* @param arg{any}
* @return {string|null|undefined}
*/
function typeOf(arg) {
if (arg === null) return null;
if (arg === undefined) return undefined;
return arg.constructor.name;
}
/**
* @description 判断数组是否不为空
* @param arr {Array} 数组
* @return {boolean}
*/
function isNotEmptyArray(arr) {
if (!arr) return false;
return arr.length !== 0;
}
/**
* @description getRunningPkg替代
* @return {null|*|string}
*/
function getRunningPkgEx() {
let node = bounds(100, 200, device.getScreenWidth(), device.getScreenHeight() - 100).getOneNodeInfo(0)
return node ? node.pkg : ""
}
/**
* @description 返回并等待
* @param times {number?} 返回次数,默认1次
* @param delay {number?} 延迟毫秒数,默认1000
*/
function backs(times, delay) {
times = times || 1
delay = delay || 1000
for (let i = 0; i < times; i++) {
back()
sleep(delay)
}
}
/**
* @description 返回桌面并等待
* @param times{number?} 等待秒数
*/
function homes(times) {
times = times * 1000 || 1000
home()
sleep(times)
}
/**
* @description 随机点击节点
* @param nodeInfo {NodeInfo?}节点信息,默认g_ret
* @param noDelay {boolean?}不加延迟,默认false,加延迟
*/
function clickPointBounds(nodeInfo, noDelay) {
nodeInfo = nodeInfo || g_ret
clickPoint(random(nodeInfo.bounds.left + 2, nodeInfo.bounds.right - 2), random(nodeInfo.bounds.top + 2, nodeInfo.bounds.bottom - 2))
if (!noDelay) {
sleep(random(500, 1000))
}
}
/**
* @description 随机点击范围
* @param x1 {number}
* @param y1{number}
* @param x2{number}
* @param y2{number}
* @param noDelay {boolean?}不加延迟,默认false,加延迟
*/
function clickPointRnd(x1, y1, x2, y2, noDelay) {
clickPoint(random(x1, x2), random(y1, y2))
if (!noDelay) {
sleep(random(500, 1000))
}
}
/**
* @description 随机点击数组
* @param arr1 {Array} bounds左上坐标 [12,2224]
* @param arr2{Array} bounds右下坐标 [195,2340]
* @param noDelay {boolean?}不加延迟,默认false,加延迟
*/
function clickPointArr(arr1, arr2, noDelay) {
clickPoint(random(arr1[0], arr2[0]), random(arr1[1], arr2[1]))
if (!noDelay) {
sleep(random(500, 1000))
}
}
/**
* @description 多点比色 配合德林取色
* @param points {string}
* @param threshold {floaty?} 0.0 ~ 1.0
* @returns {boolean} true/false
*/
function cmpColor(points, threshold) {
threshold = threshold || 1.0
return image.cmpColorEx(points, threshold, 0, 0, 0, 0)
}
/**
* @description multitouch方法进行点击
* @param node {NodeInfo?} 节点信息,默认g_ret
*/
function tapExR(node) {
node = node || g_ret
let x = random(node.bounds.left, node.bounds.right)
let y = random(node.bounds.top, node.bounds.bottom)
let touch1 = MultiPoint
.get()
.action(0).x(x).y(y).pointer(1).delay(1)
.next()
.action(2).x(x).y(y).pointer(1).delay(1)
.next()
.action(1).x(x).y(y).pointer(1).delay(1);
multiTouch(touch1, null, null, 300);
}
laoleng.app = {};
/**
* @description 打开app设置页
* @param {String} pkgName 包名
* @return {Boolean} true/false
*/
laoleng.app.openAppSetting = function (pkgName) {
return utils.openActivity({
"action": "android.settings.APPLICATION_DETAILS_SETTINGS",
"uri": "package:" + pkgName
});
}
/**
* @description shell强制关闭app
* @param {String} pkgName 包名
* @return {Boolean} true/false
*/
laoleng.app.forceKillApp = function (pkgName) {
return !!shell.execCommand("am force-stop " + pkgName)
}
/**
* @description shell清理app数据
* @param {String} pkgName 包名
* @return {Boolean} true/false
*/
laoleng.app.cleanApp = function (pkgName) {
shell.execCommand("pm clear " + pkgName)
}
/**
* @description 包名是否在前台
* @param pkgName{string} 包名
* @return {boolean} true/false
*/
laoleng.app.isRunningPkg = function (pkgName) {
return !!pkg(pkgName).getOneNodeInfo(0)
}
/**
* @description 无障碍关闭app数据[华为/小米]
* @param {String} pkgName 包名
* @return {Boolean} true/false
*/
laoleng.app.accKillApp = function (pkgName) {
logi(">>accKillApp")
homes();
this.openAppSetting(pkgName);
sleep(1000);
let timeOut = 0
while (true) {
if (findNode(textMatch("^强行停止$|^强行结束$|^结束运行$"))) {
logd("强行停止");
if (g_ret.enabled) {
findClickEx()
timeOut++;
if (timeOut >= 5) {
backs();
return false
}
} else {
backs();
return true
}
} else if (findNode(text("确定"), true)) {
logd("确定");
} else if (findNode(desc("打开设置。").pkg("com.android.systemui"))) {
logd("打开了设置框");
backs();
}
}
}
/**
* @description 获取apk图标bitmap
* @param pkgName {string} apk包名
* @return {ImageBitmap} 图标bitmap
*/
laoleng.app.getBitmap = function (pkgName) {
let packageManager, applicationInfo;
try {
packageManager = context.getApplicationContext().getPackageManager();
applicationInfo = packageManager.getApplicationInfo(pkgName, 0);
} catch (e) {
return null;
}
return packageManager.getApplicationIcon(applicationInfo).getBitmap();
}
/**
* @description 数组方法
* @type {
/**
* @author Mr_老冷 QQ:1920712147
* @date