auto.js の基本操作を超完全に網羅しており、現在は autoX.js の制御方法となっています。2023年7月9日更新!(第3章/第4章)

02_auto.jsの基本操作 3/4

記事ディレクトリ

コンソール

ログを保存する

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

トーストモニタリング

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

Web から画像を取得して保存する

//这个是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);

フローティングウィンドウ入力ボックス

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('开始运行');
    }
}

おすすめ

転載: blog.csdn.net/qq_37952052/article/details/131743472