隐藏

超全的auto.js基础操作,目前是autoX.js的控制方式

发布:2023/11/21 11:47:18作者:管理员 来源:本站 浏览次数:330

02_auto.js基础操作3/4

文章目录

    02_auto.js基础操作3/4
        控制台
            保存日志
            产生随机数
            调整控制台大小位置
            格式化输出
            控制台示例
            设置日志显示最大行数
            修改控制台界面
            终端模拟器
        设备与设备信息
            调整设备亮度
            调整设备音量
            获取设备信息
        时间与按键、触摸监听
            按键监听
            触摸监听
            通知监听
            音量健控制程序
            长按返回退出当前程序
            Toast监听
        图片与图色处理
            找图
            找出所有图
            找图并画出位置
            获取网络图片并保存
            截图并保存
            精确找色
            模糊找色
            区域找色1
            区域找色2
            实时显示触摸点颜色
            图片处理
            颜色获取和检测
            找到QQ红点位置
        文件读写
            读取文本文件
            读写文本文件
            删除所有空文件夹
            文件编码转换
            文件编码转换(高级)
            写入文本文件
        消息处理(加密、摘要、编码)
            加密解密
            消息摘要(MD5,SHA)
            base64编码
        协程
            协成HelloWorld
            ui中使用协成
        悬浮窗
            动态悬浮文字
            护眼模式
            悬浮窗输入框
            悬浮窗运行脚本按钮简单版
            悬浮文字
            悬浮运行脚本按钮

控制台
保存日志

console.setGlobalLogConfig({
    file: "/sdcard/log.txt"
});
console.log(1);
console.log(2);
console.error(3);
app.viewFile("/sdcard/log.txt");

    

产生随机数

console.show();

log("将产生5个1到100的随机数");

for(let i = 0; i < 5; i++){
    print(random(1, 100));
    print("  ");
    sleep(400);
}
print("\n");

log("将产生10个1到20的不重复随机数");

var exists = {};

for(let i = 0; i < 10; i++){
    var r;
    do{
        r = random(1, 20);
    }while(exists[r]);
    exists[r] = true;
    print(r + "  ");
    sleep(400);
}

   
调整控制台大小位置

console.show(true);
console.log("运行结束自动关闭");
console.log("调整大小...");
console.setSize(1000, 1000);
sleep(2000);
console.log("调整位置...");
console.setPosition(0, 500);
sleep(2000);

 

格式化输出

console.show();

var i = {
    name: "小明",
    age: 18,
    height: 1.72
};

console.log("大家好, 我叫%s, 今年%d岁, 身高%d米", i.name, i.age, i.height);
console.log("实际上我是一个对象啦,长这样子: %j", i);

 

控制台示例

//显示控制台
console.show();

console.verbose("这是灰色");
console.log("这是黑色");
console.info("这是红色");
console.warn("这是蓝色");
console.error("这是绿色=_=");
hey();

function hey() {
    console.trace("打印日志行数");
}

    
设置日志显示最大行数

console.show(false);
console.setMaxLines(10);
var i=0;
while(true){
    console.log(i)
    i++;
    sleep(500);
}

 

修改控制台界面


function myrandom(min,max){
    return Math.floor(Math.random() * (max - min + 1) ) + min;
}

threads.start(function () {
    console.show();
    console.setTitle("中文","#ff11ee00",30);
    console.setCanInput(false);
    var i=0;
    do {
        console.setLogSize(myrandom(4,20) );
        console.setBackgroud("#33ef0000");
        console.setCanInput(i%2==0);
        i++;
        console.log("i----->"+i);
        sleep(3000);
    } while (true);

});


终端模拟器

var sh = new Shell();
sh.setCallback({
    onOutput: function(str){
        print(str);
    }
})
console.show();
do {
    var cmd = console.rawInput();
    sh.exec(cmd);
}while(cmd != "exit");
sh.exit();

   

设备与设备信息
调整设备亮度

"ui";

ui.layout(
    <vertical padding="16">
        <checkbox id="auto" text="自动亮度"/>
        <text textColor="black" textSize="16sp" margin="8">亮度</text>
        <seekbar id="brightness" max="100"/>
    </vertical>
);

//getBrightnessMode()返回亮度模式,1为自动亮度
ui.auto.setChecked(device.getBrightnessMode() == 1);
ui.auto.setOnCheckedChangeListener(function(v, checked){
    device.setBrightnessMode(checked ? 1: 0);
});

ui.brightness.setProgress(device.getBrightness());
ui.brightness.setOnSeekBarChangeListener({
    onProgressChanged: function(seekbar, p, fromUser){
        if(fromUser){
            device.setBrightness(p);
        }
    }
});

 

调整设备音量

"ui";

ui.layout(
    <vertical padding="16">
        <text textColor="black" textSize="16sp">媒体音量</text>
        <seekbar id="music"/>

        <text textColor="black" textSize="16sp">通知音量</text>
        <seekbar id="notification"/>

        <text textColor="black" textSize="16sp">闹钟音量</text>
        <seekbar id="alarm"/>
    </vertical>
);

ui.music.setMax(device.getMusicMaxVolume());
ui.music.setProgress(device.getMusicVolume());
ui.music.setOnSeekBarChangeListener({
    onProgressChanged: function(seekbar, p, fromUser){
        if(fromUser){
            device.setMusicVolume(p);
        }
    }
});

ui.notification.setMax(device.getNotificationMaxVolume());
ui.notification.setProgress(device.getAlarmVolume());
ui.notification.setOnSeekBarChangeListener({
    onProgressChanged: function(seekbar, p, fromUser){
        if(fromUser){
            device.setNotificationVolume(p);
        }
    }
});

ui.alarm.setMax(device.getAlarmMaxVolume());
ui.alarm.setProgress(device.getAlarmVolume());
ui.alarm.setOnSeekBarChangeListener({
    onProgressChanged: function(seekbar, p, fromUser){
        if(fromUser){
            device.setAlarmVolume(p);
        }
    }
});

 

获取设备信息


console.show();

var str = "";
str += "屏幕宽度:" + device.width;
str += "\n屏幕高度:" + device.height;
str += "\nbuildId:" + device.buildId;
str += "\n主板:" + device.board;
str += "\n制造商:" + device.brand;
str += "\n型号:" + device.model;
str += "\n产品名称:" + device.product;
str += "\nbootloader版本:" + device.bootloader;
str += "\n硬件名称:" + device.hardware;
str += "\n唯一标识码:" + device.fingerprint;
str += "\nIMEI: " + device.getIMEI();
str += "\nAndroidId: " + device.getAndroidId();
str += "\nMac: " + device.getMacAddress();
str += "\nAPI: " + device.sdkInt;
str += "\n电量: " + device.getBattery();
str += "\n是否有虚拟导航: " + device.checkDeviceHasNavigationBar();
str += "\n虚拟导航高度: " + device.getVirtualBarHeigh();
log(str);

 

时间与按键、触摸监听
按键监听

"auto";

events.observeKey();

var keyNames = {
    "KEYCODE_VOLUME_UP": "音量上键",
    "KEYCODE_VOLUME_DOWN": "音量下键",
    "KEYCODE_HOME": "Home键",
    "KEYCODE_BACK": "返回键",
    "KEYCODE_MENU": "菜单键",
    "KEYCODE_POWER": "电源键",
};

events.on("key", function(code, event){
    var keyName = getKeyName(code, event);
    if(event.getAction() == event.ACTION_DOWN){
        toast(keyName + "被按下");
    }else if(event.getAction() == event.ACTION_UP){
        toast(keyName + "弹起");
    }
});

loop();



function getKeyName(code, event){
    var keyCodeStr = event.keyCodeToString(code);
    var keyName = keyNames[keyCodeStr];
    if(!keyName){
        return keyCodeStr;
    }
    return keyName;
}

   
触摸监听


events.observeTouch();

events.setTouchEventTimeout(30);

toast("请在日志中查看触摸的点的坐标");

events.on("touch", function(point){
    log(point);
});

loop();

 

通知监听

auto();
events.observeNotification();
events.onNotification(function(notification){
    printNotification(notification);
});
toast("监听中,请在日志中查看记录的通知及其内容");

function printNotification(notification){
    log("应用包名: " + notification.getPackageName());
    log("通知文本: " + notification.getText());
    log("通知优先级: " + notification.priority);
    log("通知目录: " + notification.category);
    log("通知时间: " + new Date(notification.when));
    log("通知数: " + notification.number);
    log("通知摘要: " + notification.tickerText);
}

   

音量健控制程序

"auto";

events.observeKey();

var interval = 5000;
var task = task1;

events.onKeyDown("volume_up", function(event){
    if(task == task1){
        task = task2;
    }else{
        task = task1;
    }
    toast("任务已切换");
});

events.onKeyDown("volume_down", function(event){
    toast("程序结束");
    exit();
});

task();

loop();

function task1(){
    toast("任务1运行中,音量下键结束,音量上键切换任务");
    setTimeout(task, interval);
}

function task2(){
    toast("任务2运行中,音量下键结束,音量上键切换任务");
    setTimeout(task, interval);
}

   
长按返回退出当前程序

"auto";

var 长按间隔 = 1500;

var curPackage = null;
var timeoutId = null;

events.observeKey();

events.onKeyDown("back", function(event){
    curPackage = currentPackage();
    timeoutId = setTimeout(function(){
       backBackBackBack();
    }, 长按间隔);
});

events.onKeyUp("back", function(event){
    clearTimeout(timeoutId);
});

loop();

function backBackBackBack(){
    while(curPackage == currentPackage()){
        back();
        sleep(200);
    }
}

   

Toast监听

auto();
events.observeToast();
events.onToast(function(toast){
    var pkg = toast.getPackageName();
    log("Toast内容: " + toast.getText() +
        " 来自: " + getAppName(pkg) +
        " 包名: " + pkg);
});
toast("监听中,请在日志中查看记录的Toast及其内容");

   

图片与图色处理
找图


var superMario = images.read("./super_mario.jpg");
var mario = images.read("./mario.png");
var point = findImage(superMario, mario);
toastLog(point);

superMario.recycle();
mario.recycle();

   
找出所有图


var superMario = images.read("./super_mario.jpg");
var block = images.read("./block.png");

var result = images.matchTemplate(superMario, block, {
    threshold: 0.8
}).matches;
toastLog(result);

superMario.recycle();
block.recycle();

   

找图并画出位置


var superMario = images.read("./super_mario.jpg");
var block = images.read("./block.png");
var points = images.matchTemplate(superMario, block, {
    threshold: 0.8
}).points;

toastLog(points);

var canvas = new Canvas(superMario);
var paint = new Paint();
paint.setColor(colors.parseColor("#2196F3"));
points.forEach(point => {
    canvas.drawRect(point.x, point.y, point.x + block.width, point.y + block.height, paint);
});
var image = canvas.toImage();
images.save(image, "/sdcard/tmp.png");

app.viewFile("/sdcard/tmp.png");

superMario.recycle();
block.recycle();
image.recycle();

   
获取网络图片并保存

//这个是Auto.js图标的地址
var url = "https://www.autojs.org/assets/uploads/profile/3-profileavatar.png";
var logo = images.load(url);
//保存到路径/sdcard/auto.js.png
images.save(logo, "/sdcard/auto.js.png");

    

截图并保存

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
images.saveImage(img, "/sdcard/1.png");

   

精确找色

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
//0x9966ff为编辑器紫色字体的颜色
toastLog("开始找色");
var point = findColor(img, 0x9966ff);
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}

模糊找色

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
//0x9966ff为编辑器紫色字体的颜色
toastLog("开始找色");
var point = findColor(img, 0x9966ff);
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}




区域找色1

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
toastLog("开始找色");
//指定在位置(100, 220)宽高为400*400的区域找色。
//#75438a是编辑器默认主题的棕红色字体(数字)颜色,位置大约在第5行的"2000",坐标大约为(283, 465)
var point = findColorInRegion(img, "#75438a", 90, 220, 900, 1000);
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}



区域找色2

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
//0xffffff为白色
toastLog("开始找色");
//指定在位置(90, 220)宽高为900*1000的区域找色。
//0xff00cc是编辑器的深粉红色字体(字符串)颜色
var point = findColor(img, "#ff00cc", {
    region: [90, 220, 900, 1000],
    threads: 8
});
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}

实时显示触摸点颜色

requestScreenCapture();
console.show();
events.observeTouch();
events.setTouchEventTimeout(30);
events.on("touch", function(point){
    var c = colors.toString(images.pixel(captureScreen(), point.x, point.y));
    log("(" + point.x + ", " + point.y + "): " + c);
});

 
图片处理

"ui";

var url = "https://www.autojs.org/assets/uploads/files/1540386817060-918021-20160416200702191-185324559.jpg";
var logo = null;
var currentImg = null;

events.on("exit", function(){
    if(logo != null){
        logo.recycle();
    }
    if(currentImg != null){
        currentImg.recycle();
    }
});

ui.layout(
    <vertical>
        <img id="img" w="250" h="250" url="{{url}}" />
        <scroll>
            <vertical>
                <button id="rotate" text="旋转" />
                <button id="concat" text="拼接" />
                <button id="grayscale" text="灰度化" />
                <button id="binary" text="二值化" />
                <button id="adaptiveBinary" text="自适应二值化" />
                <button id="hsv" text="RGB转HSV" />
                <button id="blur" text="模糊" />
                <button id="medianBlur" text="中值滤波" />
                <button id="gaussianBlur" text="高斯模糊" />
            </vertical>
        </scroll>
    </vertical>
);

//把一张图片设置到图片控件中
function setImage(img) {
    ui.run(() => {
        ui.img.setImageBitmap(img.bitmap);
        var oldImg = currentImg;
        //不能立即回收currentImg,因为此时img控件还在使用它,应该在下次消息循环再回收它
        ui.post(()=>{
            if(oldImg != null){
                oldImg.recycle();
            }
        });
        currentImg = img;
    });
}

//启动一个处理图片的线程
var imgProcess = threads.start(function () {
    setInterval(() => { }, 1000);
});

//处理图片的函数,把任务交给图片处理线程处理
function processImg(process) {
    imgProcess.setTimeout(() => {
        if (logo == null) {
            logo = images.load(url);
        }
        //处理图片
        var result = process(logo);
        //把处理后的图片设置到图片控件中
        setImage(result);
    }, 0);
}

var degress = 0;

ui.rotate.on("click", () => {
    processImg(img => {
        degress += 90;
        //旋转degress角度
        return images.rotate(img, degress);
    });
});

ui.concat.on("click", () => {
    processImg(img => {
        if(currentImg == null){
            toast("请先点击其他按钮,再点击本按钮");
            return img.clone();
        }
        //把currentImg拼接在img右边
        return images.concat(img, currentImg, "right");
    });
});

ui.grayscale.on("click", () => {
    processImg(img => {
        //灰度化
        return images.grayscale(img);
    });
});

ui.binary.on("click", () => {
    processImg(img => {
        var g = images.grayscale(img);
        //二值化,取灰度为30到200之间的图片
        var result = images.threshold(g, 100, 200);
        g.recycle();
        return result;
    });
});

ui.adaptiveBinary.on("click", () => {
    processImg(img => {
        var g = images.grayscale(img);
        //自适应二值化,最大值为200,块大小为25
        var result = images.adaptiveThreshold(g, 200, "MEAN_C", "BINARY", 25, 10);
        g.recycle();
        return result;
    });
});

ui.hsv.on("click", () => {
    processImg(img => {
        //RGB转HSV
        return images.cvtColor(img, "BGR2HSV");
    });
});

ui.blur.on("click", () => {
    processImg(img => {
        //模糊
        return images.blur(img, [10, 10]);
    });
});

ui.medianBlur.on("click", () => {
    processImg(img => {
        //中值滤波
        return images.medianBlur(img, 5);
    });
});

ui.gaussianBlur.on("click", () => {
    processImg(img => {
        //高斯模糊
        return images.gaussianBlur(img, [5, 5]);
    });
});

 

颜色获取和检测

if(!requestScreenCapture()){
   toast("请求截图失败");
   exit
}
sleep(2000);
var x = 760;
var y = 180;
//获取在点(x, y)处的颜色
var c = images.pixel(captureScreen(), x, y);
//显示该颜色
var msg = "";
msg += "在位置(" + x + ", " + y + ")处的颜色为" + colors.toString(c);
msg += "\nR = " + colors.red(c) + ", G = " + colors.green(c) + ", B = " + colors.blue(c);
//检测在点(x, y)处是否有颜色#73bdb6 (模糊比较)
var isDetected = images.detectsColor(captureScreen(), "#73bdb6", x, y);
msg += "\n该位置是否匹配到颜色#73bdb6: " + isDetected;
alert(msg);


找到QQ红点位置

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
launchApp("QQ");
sleep(2000);
var img = captureScreen();
toastLog("开始找色");
var point = findColor(img, "#f64d30");
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}


文件读写
读取文本文件

//文件路径
var path = "/sdcard/1.txt";
//打开文件
var file = open(path);
//读取文件的所有内容
var text = file.read();
//打印到控制台
print(text);
//关闭文件
file.close();
console.show();

    

读写文本文件

//以写入模式打开SD卡根目录文件1.txt
var file = open("/sdcard/1.txt", "w")
//写入aaaa
file.write("aaaa");
//写入bbbbb后换行
file.writeline("bbbbb");
//写入ccc与ddd两行
file.writelines(["ccc", "ddd"]);
//关闭文件
file.close();

//以附加模式打开文件
file = open("/sdcard/1.txt", "a");
//附加一行"啦啦啦啦"
file.writeline("啦啦啦啦");
//附加一行"哈哈哈哈"
file.writeline("哈哈哈哈");
//附加两行ccc, ddd
file.writelines(["ccc", "ddd"]);
//输出缓冲区
file.flush();
//关闭文件
file.close();


//以读取模式打开文件
file = open("/sdcard/test.txt", "r")
//读取一行并打印
print(file.readline());
//读取剩余所有行并打印
for each(line in file.readlines()){
  print(line)
}
file.close()

//显示控制台
console.show()

    

删除所有空文件夹

if(confirm("该操作会删除SD卡目录及其子目录下所有空文件夹,是否继续?")){
    toast("请点击右上角打开日志");
    deleteAllEmptyDirs(files.getSdcardPath());
    toast("全部完成!");
}

function deleteAllEmptyDirs(dir){
    var list = files.listDir(dir);
    var len = list.length;
    if(len == 0){
        log("删除目录 " + dir + " " + (files.remove(dir) ? "成功" : "失败"));
        return;
    }
    for(let i = 0; i < len; i++){
        var child = files.join(dir, list[i]);
        if(files.isDir(child)){
            deleteAllEmptyDirs(child);
        }
    }
}

    
文件编码转换

//以UTF-8编码打开SD卡上的1.txt文件
var f = open("/sdcard/1.txt", "r", "utf-8");
//读取文件所有内容
var text = f.read();
//关闭文件
f.close();
//以gbk编码打开SD卡上的2.txt文件
var out = open("/sdcard/2.txt", "w", "gbk");
//写入内容
out.write(text);
//关闭文件
out.close();


    

文件编码转换(高级)



convert("/sdcard/1.txt", "utf-8", "/sdcard/2.txt", "gbk");

/**
 * fromFile: 源文件路径
 * fromEncoding: 源文件编码
 * toFile: 输出文件路径
 * toEncoding: 输出文件编码
 */
function convert(fromFile, fromEncoding, toFile, toEncoding){
    fromFile = open(fromFile, "r", fromEncoding);
    toFile = open(toFile, "w", toEncoding);
    while(true){
        var line = fromFile.readline();
        if(!line)
            break;
        toFile.writeline(line);
    }
}

   

写入文本文件

//文件路径
var path = "/sdcard/1.txt";
//要写入的文件内容
var text = "Hello, AutoJs";
//以写入模式打开文件
var file = open(path, "w");
//写入文件
file.write(text);
//关闭文件
file.close();

    

消息处理(加密、摘要、编码)
加密解密

let message = "未加密字符串";
log("明文: ", message);
// 密钥,由于AES等算法要求是16位的倍数,我们这里用一个16位的密钥
let key = new $crypto.Key("password12345678");
log("密钥: ", key);
// AES加密
let aes = $crypto.encrypt(message, key, "AES/ECB/PKCS5padding");
log("AES加密后二进制数据: ", aes);
log("AES解密: ", $crypto.decrypt(aes, key, "AES/ECB/PKCS5padding", {output: 'string'}));

// RSA加密
// 生成RSA密钥
let keyPair = $crypto.generateKeyPair("RSA");
log("密钥对: ", keyPair);
// 使用私钥加密
let rsa = $crypto.encrypt(message, keyPair.privateKey, "RSA/ECB/PKCS1padding");
log("RSA私钥加密后二进制数据: ", rsa);
// 使用公钥解密
log("RSA公钥解密: ", $crypto.decrypt(rsa, keyPair.publicKey, "RSA/ECB/PKCS1padding", {output: 'string'}));

    
消息摘要(MD5,SHA)


// 字符串消息摘要
let message = "Hello, Autox.js";
// 输出各种消息摘要算法结果的hex值
log("字符串: ", message);
log("MD5: ", $crypto.digest(message, "MD5"));
log("SHA1: ", $crypto.digest(message, "SHA-1"));
log("SHA256: ", $crypto.digest(message, "SHA-256"));

// 输出各种消息摘要算法结果的base64值
log("MD5 [base64]: ", $crypto.digest(message, "MD5", {output: 'base64'}));
log("SHA1 [base64]: ", $crypto.digest(message, "SHA-1", {output: 'base64'}));
log("SHA256 [base64]: ", $crypto.digest(message, "SHA-256", {output: 'base64'}));


// 文件消息摘要
let file = "/sdcard/脚本/_test_for_message_digest.js"
// 写入文件内容,提供为后续计算MD5等
$files.write(file, "Test!");
log("文件: ", file);
log("MD5: ", $crypto.digest(file, "MD5", {input: 'file'}));
log("SHA1: ", $crypto.digest(file, "SHA-1", {input: 'file'}));
log("SHA256: ", $crypto.digest(file, "SHA-256", {input: 'file'}));

    
base64编码

let message = "autox.js";
log("明文: ", message);

let base64encode = $base64.encode(message);
log("Base64编码: ", base64encode);

let message2 = "YXV0b3guanM=";
log("明文2: ", message2);

let base64decode = $base64.decode(message2);
log("Base64解码: ", base64decode);

 

协程
协成HelloWorld

// 注意,要使用协程这个特性,必须使用项目功能,并且在project.json配置好features属性


// delay不同于sleep,不会阻塞当前线程
function delay(millis) {
    var cont = continuation.create();
    setTimeout(()=>{
        cont.resume();
    }, millis);
    cont.await();
}

// 异步IO例子,在另一个线程读取文件,读取完成后返回当前线程继续执行
function read(path) {
    var cont = continuation.create();
    threads.start(function(){
        try {
            cont.resume(files.read(path));
        }catch(err){
            cont.resumeError(err);
        }
    });
    return cont.await();
}

// 使用Promise和协程的例子
function add(a, b) {
    return new Promise(function(resolve, reject) {
        var sum = a + b;
        resolve(sum);
    });
}

toastLog("Hello, Continuation!");

//3秒后发出提示
setTimeout(()=>{
    toastLog("3秒后....");
}, 3000);

// 你可以尝试把delay更换成sleep,看会发生什么!
delay(6000);
toastLog("6秒后...");

try {
    toastLog("读取文件hello.txt: " + read("./hello.txt"));
}catch(err){
    console.error(err);
}

var sum = add(1, 2).await();
toastLog("1 + 2 = " + sum);

// project.json
{
  "name": "协程HelloWorld",
  "main": "main.js",
  "ignore": [
    "build"
  ],
  "packageName": "com.example.cont.helloworld",
  "versionName": "1.0.0",
  "versionCode": 1,
  "useFeatures": ["continuation"]
}

    

ui中使用协成

"ui";

ui.layout(
    <frame bg="#4fc3f7">
        <text textColor="white" textSize="18sp" layout_gravity="center">
            UI中使用协程
        </text>
    </frame>
);

continuation.delay(5000);
if (!requestScreenCapture()) {
    dialogs.alert("请授予软件截图权限").await();
}


// 退出应用对话框
ui.emitter.on("back_pressed", function (e) {
    e.consumed = true;
    let exit = dialogs.confirm("确定要退出程序").await();
    if (exit) {
        ui.finish();
    }
});

// project.json
{
  "name": "协程UI示例",
  "main": "main.js",
  "ignore": [
    "build"
  ],
  "packageName": "com.example.cont.ui",
  "versionName": "1.0.0",
  "versionCode": 1,
  "useFeatures": ["continuation"]
}


悬浮窗
动态悬浮文字

var window = floaty.window(
    <frame gravity="center">
        <text id="text" textSize="16sp" textColor="#f44336"/>
    </frame>
);

window.exitOnClose();

window.text.click(()=>{
    window.setAdjustEnabled(!window.isAdjustEnabled());
});

setInterval(()=>{
    //对控件的操作需要在UI线程中执行
    ui.run(function(){
        window.text.setText(dynamicText());
    });
}, 1000);

function dynamicText(){
    var date = new Date();
    var str = util.format("时间: %d:%d:%d\n", date.getHours(), date.getMinutes(), date.getSeconds());
    str += util.format("内存使用量: %d%%\n", getMemoryUsage());
    str += "当前活动: " + currentActivity() + "\n";
    str += "当前包名: " + currentPackage();
    return str;
}

//获取内存使用率
function getMemoryUsage(){
    var usage = (100 * device.getAvailMem() / device.getTotalMem());
    //保留一位小数
    return Math.round(usage * 10) / 10;
}

 
护眼模式

var w = floaty.rawWindow(
    <frame gravity="center" bg="#44ffcc00"/>
);

w.setSize(-1, -1);
w.setTouchable(false);

setTimeout(()=>{
    w.close();
}, 60000);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

悬浮窗输入框

var window = floaty.window(
    <vertical>
        <input id="input" text="请输入你的名字" textSize="16sp" focusable="true"/>
        <button id="ok" text="确定"/>
    </vertical>
);

window.exitOnClose();

toast("长按确定键可调整位置");

window.input.on("key", function(keyCode, event){
    if(event.getAction() == event.ACTION_DOWN && keyCode == keys.back){
        window.disableFocus();
        event.consumed = true;
    }
});

window.input.on("touch_down", ()=>{
    window.requestFocus();
    window.input.requestFocus();
});

window.ok.on("click", ()=>{
    toast("傻瓜! " + window.input.text());
    window.disableFocus();
});

window.ok.on("long_click", ()=>{
    window.setAdjustEnabled(!window.isAdjustEnabled());
});

setInterval(()=>{}, 1000);

   

悬浮窗运行脚本按钮简单版

var path = "/sdcard/脚本/test.js";
if(!files.exists(path)){
    toast("脚本文件不存在: " + path);
    exit();
}
var window = floaty.window(
    <frame>
        <button id="action" text="开始运行" w="90" h="40" bg="#77ffffff"/>
    </frame>
);

window.exitOnClose();

var execution = null;

window.action.click(()=>{
    if(window.action.getText() == '开始运行'){
        execution = engines.execScriptFile(path);
        window.action.setText('停止运行');
    }else{
        if(execution){
            execution.getEngine().forceStop();
        }
        window.action.setText('开始运行');
    }
});

window.action.longClick(()=>{
   window.setAdjustEnabled(!window.isAdjustEnabled());
   return true;
});

setInterval(()=>{}, 1000);

    
悬浮文字

var window = floaty.window(
    <frame gravity="center">
        <text id="text" text="点击可调整位置" textSize="16sp"/>
    </frame>
);

window.exitOnClose();

window.text.click(()=>{
    window.setAdjustEnabled(!window.isAdjustEnabled());
});

setInterval(()=>{}, 1000);

 

悬浮运行脚本按钮

var path = "/sdcard/脚本/test.js";
if(!files.exists(path)){
    toast("脚本文件不存在: " + path);
    exit();
}
var window = floaty.window(
    <frame>
        <button id="action" text="开始运行" w="90" h="40" bg="#77ffffff"/>
    </frame>
);

setInterval(()=>{}, 1000);

var execution = null;

//记录按键被按下时的触摸坐标
var x = 0, y = 0;
//记录按键被按下时的悬浮窗位置
var windowX, windowY;
//记录按键被按下的时间以便判断长按等动作
var downTime;

window.action.setOnTouchListener(function(view, event){
    switch(event.getAction()){
        case event.ACTION_DOWN:
            x = event.getRawX();
            y = event.getRawY();
            windowX = window.getX();
            windowY = window.getY();
            downTime = new Date().getTime();
            return true;
        case event.ACTION_MOVE:
            //移动手指时调整悬浮窗位置
            window.setPosition(windowX + (event.getRawX() - x),
                windowY + (event.getRawY() - y));
            //如果按下的时间超过1.5秒判断为长按,退出脚本
            if(new Date().getTime() - downTime > 1500){
                exit();
            }
            return true;
        case event.ACTION_UP:
            //手指弹起时如果偏移很小则判断为点击
            if(Math.abs(event.getRawY() - y) < 5 && Math.abs(event.getRawX() - x) < 5){
                onClick();
            }
            return true;
    }
    return true;
});

function onClick(){
    if(window.action.getText() == '开始运行'){
        execution = engines.execScriptFile(path);
        window.action.setText('停止运行');
    }else{
        if(execution){
            execution.getEngine().forceStop();
        }
        window.action.setText('开始运行');
    }
}