Safety Guest'T blog

  • 控制台
  • 保存日志
  • 产生随机数
  • 调整控制台大小位置
  • 格式化输出
  • 控制台示例
  • 设置日志显示最大行数
  • 修改控制台界面
  • 终端模拟器
  • 设备与设备信息
  • 调整设备亮度
  • 调整设备音量
  • 获取设备信息
  • 时间与按键、触摸监听
  • 按键监听
  • 触摸监听
  • 通知监听
  • 音量健控制程序
  • 长按返回退出当前程序
  • Toast监听
  • 图片与图色处理
  • 找图
  • 找出所有图
  • 找图并画出位置
  • 获取网络图片并保存
  • 截图并保存
  • 精确找色
  • 模糊找色
  • 区域找色1
  • 区域找色2
  • 实时显示触摸点颜色
  • 图片处理
  • 颜色获取和检测
  • 找到QQ红点位置
  • 文件读写
  • 读取文本文件
  • 读写文本文件
  • 删除所有空文件夹
  • 文件编码转换
  • 文件编码转换(高级)
  • 写入文本文件
  • 消息处理(加密、摘要、编码)
  • 加密解密
  • 消息摘要(MD5,SHA)
  • base64编码
  • 协程
  • 协成HelloWorld
  • ui中使用协成
  • 悬浮窗
  • 动态悬浮文字
  • 护眼模式
  • 悬浮窗输入框
  • 悬浮窗运行脚本按钮简单版
  • 悬浮文字
  • 悬浮运行脚本按钮
  • 首页
  • 归档
  • 软件开发
  • 网络安全
  • 逆向破解
  • 人工智能
  • 资源分享
  • 区 块 链
  • 隐私政策
  • 友情链接

AutoX.js基础操作(第3/4章)

  • Tz
  • 2024-05-11
  • 0

控制台

保存日志

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);

控制台示例

<em>//显示控制台
</em><em></em>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>
);

<em>//getBrightnessMode()返回亮度模式,1为自动亮度
</em><em></em>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();

获取网络图片并保存

<em>//这个是Auto.js图标的地址
</em><em></em>var url = "https://www.autojs.org/assets/uploads/profile/3-profileavatar.png";
var logo = images.load(url);
<em>//保存到路径/sdcard/auto.js.png
</em><em></em>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();
<em>//0x9966ff为编辑器紫色字体的颜色
</em><em></em>toastLog("开始找色");
var point = findColor(img, 0x9966ff);
if(point){
    toastLog("x = " + point.x + ", y = " + point.y);
}else{
    toastLog("没有找到");
}

模糊找色

if(!requestScreenCapture()){
    toast("请求截图失败");
    exit();
}
var img = captureScreen();
<em>//0x9966ff为编辑器紫色字体的颜色
</em><em></em>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("开始找色");
<em>//指定在位置(100, 220)宽高为400*400的区域找色。
</em><em>//#75438a是编辑器默认主题的棕红色字体(数字)颜色,位置大约在第5行的"2000",坐标大约为(283, 465)
</em><em></em>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();
<em>//0xffffff为白色
</em><em></em>toastLog("开始找色");
<em>//指定在位置(90, 220)宽高为900*1000的区域找色。
</em><em>//0xff00cc是编辑器的深粉红色字体(字符串)颜色
</em><em></em>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>
);

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

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

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

var degress = 0;

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

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

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

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

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

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

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

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

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

颜色获取和检测

if(!requestScreenCapture()){
   toast("请求截图失败");
   exit
}
sleep(2000);
var x = 760;
var y = 180;
<em>//获取在点(x, y)处的颜色
</em><em></em>var c = images.pixel(captureScreen(), x, y);
<em>//显示该颜色
</em><em></em>var msg = "";
msg += "在位置(" + x + ", " + y + ")处的颜色为" + colors.toString(c);
msg += "\nR = " + colors.red(c) + ", G = " + colors.green(c) + ", B = " + colors.blue(c);
<em>//检测在点(x, y)处是否有颜色#73bdb6 (模糊比较)
</em><em></em>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("没有找到");
}

文件读写

读取文本文件

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

读写文本文件

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

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


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

<em>//显示控制台
</em><em></em>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);
        }
    }
}

文件编码转换

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

文件编码转换(高级)

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

<em>/**
</em><em> * fromFile: 源文件路径
</em><em> * fromEncoding: 源文件编码
</em><em> * toFile: 输出文件路径
</em><em> * toEncoding: 输出文件编码
</em><em> */</em>
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);
    }
}

写入文本文件

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

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

加密解密

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

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

消息摘要(MD5,SHA)

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

<em>// 输出各种消息摘要算法结果的base64值
</em><em></em>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'}));


<em>// 文件消息摘要
</em><em></em>let file = "/sdcard/脚本/_test_for_message_digest.js"
<em>// 写入文件内容,提供为后续计算MD5等
</em><em></em>$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

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

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

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

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

toastLog("Hello, Continuation!");

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

<em>// 你可以尝试把delay更换成sleep,看会发生什么!
</em><em></em>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);

<em>// project.json
</em><em></em>{
  "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();
}


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

<em>// project.json
</em><em></em>{
  "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(()=>{
    <em>//对控件的操作需要在UI线程中执行
</em><em></em>    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;
}

<em>//获取内存使用率
</em><em></em>function getMemoryUsage(){
    var usage = (100 * device.getAvailMem() / device.getTotalMem());
    <em>//保留一位小数
</em><em></em>    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);

悬浮窗输入框

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;

<em>//记录按键被按下时的触摸坐标
</em><em></em>var x = 0, y = 0;
<em>//记录按键被按下时的悬浮窗位置
</em><em></em>var windowX, windowY;
<em>//记录按键被按下的时间以便判断长按等动作
</em><em></em>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:
            <em>//移动手指时调整悬浮窗位置
</em><em></em>            window.setPosition(windowX + (event.getRawX() - x),
                windowY + (event.getRawY() - y));
            <em>//如果按下的时间超过1.5秒判断为长按,退出脚本
</em><em></em>            if(new Date().getTime() - downTime > 1500){
                exit();
            }
            return true;
        case event.ACTION_UP:
            <em>//手指弹起时如果偏移很小则判断为点击
</em><em></em>            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('开始运行');
    }
}
© 2025 Safety Guest'T blog
Theme by Wing
渝ICP备 2021011909号 渝公网安备 50019002502382号
  • {{ item.name }}
  • {{ item.name }}