通过自动化脚本自动设置锁定app,防止其被清理掉

一、为什么要锁定App

在移动端自动化脚本的长期运行过程中,最令人头疼的问题莫过于脚本执行到一半,冰狐智能辅助App被系统后台清理掉了。安卓系统(尤其是小米MIUI、华为EMUI等深度定制系统)出于省电和内存管理的目的,会对后台运行的应用进行限制和清理。一旦冰狐App被清理,正在执行的脚本就会中断,导致自动化任务失败。

锁定App的本质,是告诉系统:“这个应用很重要,请不要清理我。”锁定后,系统会给被锁定的应用一个较高的优先级,在清除内存等操作时不会自动将其杀掉。手动操作路径通常是:手机管家→优化加速→右上角的设置图标→锁定任务,然后选择需要锁定的应用。但如果设备数量众多,逐一手动操作显然不现实。本文介绍如何编写脚本自动化完成这一操作。

二、脚本设计思路

本文的脚本以小米手机的安全中心(com.miui.securitycenter)为目标应用,通过以下步骤实现自动锁定指定App:

  1. 启动安全中心:使用launchApp启动小米安全中心

  2. 进入设置页面:通过switchPage从“优化加速”切换到“设置”

  3. 进入锁定任务:在设置中找到“锁定任务”并进入

  4. 遍历应用列表:在锁定任务列表中滚动查找目标App

  5. 执行锁定操作:找到目标App后,若未锁定则点击勾选

  6. 异常处理:处理可能出现的弹窗(如“用户须知”)

三、核心API解析

本脚本主要使用以下冰狐平台API:

1. launchApp(packageName)

启动指定包名的应用。返回1表示成功,0表示该App未安装,-1表示启动失败。

launchApp('com.miui.securitycenter')

2. findView(tag, options)

根据tag查找UI控件,是脚本中最核心的控件定位函数。tag支持多种格式:

  • txt:设置 —— 查找文本为“设置”的控件

  • txt*:用户须知 —— 查找文本包含“用户须知”的控件

  • cn:androidx.recyclerview.widget.RecyclerView —— 按类名查找

options中的maxStep控制最大查找步数,failed指定查找失败时的回调函数。

3. switchPage(fromTag, toTag, options)

从当前页面切换到目标页面。本质是在当前界面查找toTag对应的控件并点击,若找不到则返回空数组。options中的click: true表示使用原生点击,failed指定失败回调。

4. scroll(direction, options)

在屏幕上执行滚动操作。direction'up''down'type: 2表示在指定容器内滚动,root指定滚动根控件。

5. click(view, options)

点击指定的控件节点。afterWait指定点击后等待时间(毫秒)。

6. getAppName()

获取当前脚本所属应用的名称,用于与锁定任务列表中的应用名称进行匹配。

四、完整源码

import sys_xiaomi_runtime;

/**
 * 冰狐智能辅助脚本 - 自动锁定指定App防止被系统清理
 * 适用平台:小米手机(MIUI系统)
 * 核心功能:通过安全中心的"锁定任务"功能,将当前App锁定
 * 
 * @returns {number} 1表示锁定成功,-1表示失败
 */
function main() {
    var result = -1;

    // 1. 启动小米安全中心
    if (!launchApp('com.miui.securitycenter')) {
        console.error('启动安全中心失败');
        return result;
    }

    // 2. 等待安全中心主界面加载完成
    var ret = waitAppLaunched('txt:安全中心', {failed: exitPopup, maxStep: 30});
    if (ret.length <= 0) {
        console.error('找不到安全中心主界面');
        return result;
    }

    // 3. 进入设置页面(从"优化加速"切换到"设置")
    ret = switchPage('txt:设置', 'txt:优化加速', {click: true, failed: exitPopup});
    if (ret.length <= 0) {
        console.error('进入优化加速设置失败');
        return result;
    }

    // 4. 进入锁定任务页面
    ret = switchPage('txt:优化加速', 'txt:锁定任务', {click: true, failed: exitPopup});
    if (ret.length <= 0) {
        console.error('进入锁定任务失败');
        return result;
    }

    // 5. 进入锁定任务列表(从"锁定任务"切换到"屏幕录制|收音机"等目标)
    ret = switchPage('txt:锁定任务', 'txt:屏幕录制|txt:收音机', {click: true, failed: exitPopup});
    if (ret.length <= 0) {
        console.error('进入锁定任务列表失败');
        return result;
    }

    // 6. 获取RecyclerView容器(应用列表)
    var container = findView('cn:androidx.recyclerview.widget.RecyclerView', {maxStep: 10});
    var count = 0;
    var appName = getAppName();  // 获取当前App名称

    // 7. 遍历应用列表,查找目标App
    while (container.length > 0 && count < 20) {
        var find = false;

        // 遍历容器中的每个应用项
        for (var item of container.views[0]) {
            // 情况一:应用名称直接作为TextView子控件
            if (item[1].className == 'android.widget.TextView' && item[1].text == appName) {
                if (!item[2].checked) {
                    click(item, {click: true, afterWait: 1000});
                }
                find = true;
                break;
            }
            // 情况二:应用名称在子控件的子控件中(嵌套结构)
            else if (item[1][0].className == 'android.widget.TextView' && item[1][0].text == appName) {
                if (!item[2].checked) {
                    click(item, {click: true, afterWait: 1000});
                }
                find = true;
                break;
            }
        }

        if (find) {
            result = 1;
            console.log('成功锁定App: ' + appName);
            break;
        }

        // 未找到则向上滚动,继续查找
        count++;
        console.log('滚动查找第' + count + '次');
        scroll('up', {type: 2, root: container.views[0], afterWait: 1000});
        container = findView('cn:androidx.recyclerview.widget.RecyclerView', {maxStep: 10});
    }

    if (result == -1) {
        console.error('在锁定任务列表中未找到App: ' + appName);
    }

    // 8. 退出处理
    exitAppDeal();
    return result;
}

/**
 * 弹窗处理函数
 * 处理可能出现的"用户须知"等弹窗
 */
function exitPopup() {
    // 检查是否存在"用户须知"弹窗
    var ret = findView('txt*:用户须知', {maxStep: 1});
    if (ret.length > 0 && ret.views[0].text.includes('用户须知')) {
        // 点击"同意"按钮关闭弹窗
        clickByTag('txt:同意', {click: true});
        console.log('已处理用户须知弹窗');
    } else {
        // 调用全局弹窗处理
        globalExitPopup();
    }
}

五、脚本执行流程详解

步骤1:启动安全中心

launchApp('com.miui.securitycenter')通过包名启动小米安全中心。小米安全中心的包名是com.miui.securitycenter,这是MIUI系统内置的安全管理应用。

步骤2-5:页面导航

脚本使用switchPage函数实现多级页面跳转。switchPage的典型用法是:先查找fromTag对应的控件并点击,然后检查toTag对应的控件是否出现来判断跳转是否成功。

导航路径为:

  • 安全中心主界面 → 优化加速(点击"设置"图标)

  • 优化加速 → 锁定任务(点击"优化加速"进入)

  • 锁定任务 → 锁定任务列表

每一级跳转都指定了failed: exitPopup,当控件查找失败时会自动调用弹窗处理函数。

步骤6-7:查找并锁定App

这是脚本的核心逻辑。首先通过findView获取RecyclerView容器——这是安卓应用中常用的列表控件,锁定任务中的应用列表正是由它承载的。

然后获取当前脚本所属App的名称(getAppName()),在列表中逐项比对。由于不同MIUI版本中列表项的结构可能略有差异,脚本考虑了两种情况:

  • 应用名称直接作为TextView子控件

  • 应用名称在更深层的嵌套结构中

找到目标后,检查checked属性判断是否已锁定,若未锁定则执行点击操作。

如果当前屏幕未显示目标App,脚本会执行向上滚动操作(scroll('up')),然后重新获取容器继续查找,最多尝试20次。

步骤8:异常弹窗处理

exitPopup函数用于处理脚本执行过程中可能出现的弹窗。当switchPagefindViewfailed回调被触发时,会调用此函数。它会检查是否存在"用户须知"弹窗,若存在则点击"同意"按钮关闭它。

六、注意事项与最佳实践

1. 权限准备

脚本运行前需确保冰狐智能辅助已开启无障碍权限,否则无法实现控件查找和点击操作。

2. 不同MIUI版本的适配

不同MIUI版本中,安全中心的界面布局可能存在差异。如果脚本执行失败,建议使用冰狐的「获取UI树」功能查看当前页面的控件结构,根据实际情况调整findView的tag参数。

3. 执行超时控制

脚本中的maxStep参数控制查找控件的最大步数,避免无限等待。count < 20限制了滚动查找的最大次数,防止死循环。

4. 日志记录

脚本中大量使用console.logconsole.error输出执行日志,方便调试和问题定位。

七、总结

本文通过一个完整的冰狐智能辅助脚本,展示了如何使用平台提供的launchAppfindViewswitchPagescrollclick等API,自动化完成小米手机中App锁定操作。这套方案可以有效防止冰狐智能辅助在后台运行时被系统清理,保障自动化脚本的长期稳定执行。

脚本采用模块化设计,核心逻辑清晰,异常处理完善,开发者可以根据实际需求进行扩展——例如支持更多手机品牌、批量锁定多个App、或集成到更大的自动化流程中。冰狐智能辅助平台以JavaScript作为统一脚本语言,语法简洁,API开箱即用,是移动端自动化开发的得力工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值