在移动自动化测试和批量设备管控场景中,经常需要在多台设备上部署同一个APP——检查应用是否已安装、版本是否最新,若不存在或版本过低则自动下载安装,最后启动应用。本文将深入解析这一实现方案。
一、为什么需要自动安装与启动
在实际的自动化运维或测试场景中,手动为每一台手机安装APP不仅效率低下,还容易因操作失误导致流程中断。尤其在批量设备管理、应用版本更新、自动化测试环境搭建等场景中,一个能够自动检测、下载、安装并启动APP的脚本可以大幅提升工作效率。冰狐智能辅助平台正是为了解决这类问题而设计的轻量化自动化工具。
二、核心API解析
冰狐平台为APP自动化操作提供了一系列封装好的系统级API。在本方案中主要涉及以下几类:
2.1 应用信息获取类
-
getAppVersion(packageName):获取指定包名应用的已安装版本号,返回字符串类型版本号 -
getAppName(packageName):获取指定包名应用的名称,若应用未安装则返回空字符串 -
getLatestAppVersion(packageName):获取指定应用的最新版本号(需平台支持版本查询服务)
2.2 应用操作类
-
launchApp(packageName):启动指定包名的应用,成功返回1,失败返回0 -
installApp(packageName)或downloadApp(packageName):下载并安装指定应用 -
install(apkPath):安装指定路径的APK文件
2.3 控件操作类
-
findView(tag, options):查找界面中的UI控件,是控件操作的核心方法 -
click(view, options):点击指定控件 -
clickByTag(tag, options):通过标签直接点击控件 -
gestureClick(x, y, options):通过坐标执行手势点击
2.4 其他辅助类
-
sleep(milliseconds):暂停脚本执行指定毫秒数 -
console.log(message):输出日志信息
三、完整源码解析
下面是完整的实现源码,包含主函数、版本比较函数和安装函数三个核心部分:
3.1 主函数 — main
// app不存在则安装,版本低则更新,最后再启动app
function main(packageName, autoInstall=true, checkUpdate=true, afterWait=6000) {
var result = false, version = getAppVersion(packageName), appName = getAppName(packageName);
// 情况一:应用未安装
if (appName == '') {
console.log('没有安装app');
if (autoInstall) {
if (installApp(packageName)) {
result = 1 == launchApp(packageName);
}
}
} else {
// 情况二:应用已安装,检查是否需要更新
if (checkUpdate) {
var latestVersion = getLatestAppVersion(packageName);
if (latestVersion != '') {
var version = getAppVersion(packageName);
if (compareVersion(latestVersion, version)) {
// 版本过低,执行更新安装
if (!installApp(packageName)) {
console.log('安装失败');
}
}
}
}
// 启动应用
result = 1 == launchApp(packageName);
}
// 启动成功后处理权限弹窗
if (result) {
clickByTag('txt:允许', {click: true, maxStep: 8});
sleep(afterWait);
}
return result;
}
主函数逻辑流程:
-
首先通过
getAppName检查应用是否已安装,若返回空字符串则表示未安装 -
未安装:若
autoInstall为true,调用installApp执行安装,安装成功后启动应用 -
已安装:若
checkUpdate为true,获取最新版本号并与当前版本比较,若最新版本更高则执行更新安装 -
最后启动应用,并处理小米手机上常见的“允许”权限弹窗
3.2 版本比较函数 — compareVersion
function compareVersion(newVersion, oldVersion) {
if (newVersion && oldVersion) {
newVersion = newVersion.trim();
oldVersion = oldVersion.trim();
var newArr = newVersion.split('.'), oldArr = oldVersion.split('.');
var size = Math.min(newArr.length, oldArr.length);
for (var i = 0; i < size; ++i) {
var newV = parseInt(newArr[i]);
var oldV = parseInt(oldArr[i]);
if (newV > oldV) {
return true;
} else if (newV < oldV) {
break;
}
}
}
return false;
}
版本比较采用标准的语义化版本号比较方式(如1.2.3),逐段比较数字大小。若新版本的任一段大于旧版本的对应段,则认为需要更新。
3.3 安装函数 — installApp
function installApp(packageName) {
var savedPath = downloadApp(packageName);
if (savedPath != '') {
if (install(savedPath)) {
// 开始点击安装界面
console.log('开始点击安装界面');
sleep(2000);
var findInstall = false, clickInstall = false, startTime = new Date().getTime();
while (!clickInstall && (new Date().getTime() - startTime) < 100000) {
var ret = findView('txt*:解析软件包时出现问题|id:com.miui.packageinstaller:id/install_btn|txt:继续安装|txt*:无视风险安装|txt:退出登录');
if (ret.length > 0) {
if (ret.tag == 'com.miui.packageinstaller:id/install_btn' || ret.tag == '继续安装') {
click(ret.views[0], {click: true});
} else if (ret.tag == '退出登录') {
break;
} else if (ret.tag == '无视风险安装') {
var view = ret.views[0];
gestureClick(view.right - 100, (view.top + view.bottom) / 2, {afterWait:1000});
} else {
console.log('解析软件包失败');
clickByTag('txt:确定', {click: true});
break;
}
findInstall = true;
}
if (findInstall) {
ret = findView('txt:确定|id:com.miui.packageinstaller:id/done_button');
if (ret.length > 0) {
click(ret.views[0], {click: true});
clickInstall = true;
}
}
}
console.log('完成安装:' + clickInstall);
return clickInstall;
} else {
console.log('install failed:');
}
}
return false;
}
安装函数的核心机制:
-
调用
downloadApp下载APK文件到本地,返回保存路径 -
调用
install拉起系统安装界面 -
安装界面适配:不同品牌手机的安装界面控件差异显著,本函数针对小米手机做了专门适配:
-
通过
findView匹配多种可能的安装按钮(install_btn、继续安装、无视风险安装等) -
针对“无视风险安装”按钮,由于可能无法直接点击,采用坐标点击方式(按钮右侧100像素处)
-
安装完成后点击“完成”或“确定”按钮
-
-
超时控制:安装过程最多等待100秒(100000毫秒),避免无限等待
四、在小米手机上的特殊适配
小米手机的安装界面有几个特点需要特别注意:
1. “无视风险安装”按钮:小米在安装非应用商店来源的APK时会弹出风险提示,需要点击“无视风险安装”才能继续。该按钮有时无法通过常规的click方法点击,因此代码中使用了gestureClick通过坐标点击的方式处理。
2. 权限弹窗:应用首次启动时会弹出各种权限申请弹窗,主函数中通过clickByTag('txt:允许', {click: true, maxStep: 8})统一处理,最多尝试查找8次。
3. 安装界面控件ID:小米系统安装器的按钮ID为com.miui.packageinstaller:id/install_btn和com.miui.packageinstaller:id/done_button,这些是通过分析UI树获取的。
五、使用示例
调用主函数只需一行代码:
// 检查并安装微信,安装成功后启动,等待6秒
main('com.tencent.mm', true, true, 6000);
参数说明:
-
packageName:目标应用的包名(必填) -
autoInstall:是否自动安装(默认true) -
checkUpdate:是否检查更新(默认true) -
afterWait:启动后等待时间(默认6000毫秒)
六、注意事项
1. 权限配置:使用冰狐平台的控件操作功能前,需在手机设置中开启冰狐智能辅助的无障碍权限。
2. 设备品牌差异:本文代码主要针对小米手机适配,若需兼容华为、OPPO、vivo等其他品牌,需要根据各品牌的安装界面控件特征补充相应的查找和点击逻辑。
3. 版本查询服务:getLatestAppVersion函数依赖平台后端服务支持,需要确保设备联网且平台已配置相应的版本查询接口。
4. 存储空间:下载APK文件需要手机有足够的存储空间,建议定期清理下载目录。
通过上述完整的实现方案,开发者可以轻松在小米手机上实现APP的自动检测、下载、安装和启动全流程,大幅提升设备管理和自动化测试的效率。

9165

被折叠的 条评论
为什么被折叠?



