如何用电脑批量操作多部手机

如果你有很多手机,然后需要在这些手机上同时执行相同的操作,这个时候如果能有一种办法批量操作,将会大大提高效率,节省很多时间。本文将介绍基于uiautomator2实现的群控手机方案。

uiautomator2 是 一种 Android 自动化测试框架,提供了点击、长按、输入文本、滑动、拖拽、截屏等方法,能够模拟用户的各种动作。

本方案采用python的web端框架django+vue前端框架实现,支持在页面选择手机,执行配置的命令,多部手机会同时执行操作(页面做的比较简陋,见谅)。

大致的流程也比较简单,基于在页面配置的命令,调用uiautomator2的相关api实现,有兴趣的朋友也可以了解下uiautomator2相关的接口,动手来实现一遍

这里贴上前端的实现代码

<template><div class="common-layout"><el-container><el-header><div style="font-weight: bolder;text-align: center;font-size: 30px">手机群控</div></el-header><el-main><el-row><el-col :span="12"><el-card class="box-card"><div style="display: flex;justify-content: space-between;align-items:center"><div style="font-weight: bolder;">设备列表</div><el-button link type="text" @click="getDeviceList">刷新</el-button></div><el-table :data="deviceListData" style="width: 100%;" height="75vh" @selection-change="selectDevices" ref="deviceTable"><el-table-column type="selection" width="55"/><el-table-column prop="sn" label="设备编号"/><el-table-column prop="name" label="设备名称"/><el-table-column prop="status" label="状态"/><el-table-column label="操作"><template slot-scope="scope"><el-button link type="text" size="small" @click="editDevice(scope.row)">编辑</el-button><!--<el-button link type="primary" size="small">删除</el-button>--></template></el-table-column></el-table></el-card></el-col><el-col :span="12"><el-card class="box-card"><div style="display: flex;justify-content: space-between;align-items:center"><div style="font-weight: bolder;">命令列表</div><el-button link type="text" @click="addCommandVisible = true">添加</el-button></div><el-table :data="commandListData" style="width: 100%" height="75vh" ><el-table-column width="55"/><el-table-column prop="name" label="名称"/><el-table-column prop="creatTime" label="创建时间"/><el-table-column label="操作"><template slot-scope="scope"><el-button link type="primary" size="small" @click="updateCommand(scope.row)">编辑</el-button><el-button link type="primary" size="small" @click="deleteCommand(scope.row.name)">删除</el-button><el-button link type="primary" size="small" @click="executeCommand(scope.row.name)">执行</el-button></template></el-table-column></el-table></el-card></el-col></el-row></el-main></el-container><el-dialog :visible.sync="addCommandVisible" title="添加/编辑命令"><el-input v-model="commandInfo.name" autocomplete="off" placeholder="请输入命令名称"></el-input><el-table :row-class-name="tableRowClassName" :data="commandInfo.commands" border style="width: 100%"><el-table-column align="center" width="100px" type="index" label="序号"></el-table-column><el-table-column align="center" prop="operation" label="操作"><template slot-scope="scope"><el-select @change="operationChange(scope.row.operation,scope.row.index)" size="small"v-model="scope.row.operation" placeholder="请选择操作类型"><el-option v-for="item in operationOption" :key="item.value" :label="item.label":value="item.value"></el-option></el-select></template></el-table-column><el-table-column align="center" prop="param" label="参数"><template #default="scope"><el-input size="small" v-model="scope.row.param" placeholder="非必填,有则填写"></el-input></template></el-table-column><el-table-column align="center" prop="delayTime" label="延时"><template #default="scope"><el-input size="small" v-model="scope.row.delayTime" placeholder="填写延时时长,单位秒"></el-input></template></el-table-column><el-table-column align="center" prop="date" label="操作"><template slot-scope="scope"><el-button link type="primary" size="small" @click="addForm">添加</el-button><el-button link type="primary" size="small" v-if="commandInfo.commands.length>1"@click="removeIdx(scope.row,scope.row.index)" style="color:rgb(216,30,6)">删除</el-button></template></el-table-column></el-table><template #footer><span class="dialog-footer"><el-button @click="addCommandVisible = false">取消</el-button><el-button type="primary" @click="addCommand">确定</el-button></span></template></el-dialog><el-dialog title="编辑设备" :visible.sync="updateDeviceVisible"><el-form :model="deviceInfo"><el-form-item label="设备编号" :label-width="formLabelWidth"><el-input v-model="deviceInfo.sn" autocomplete="off" disabled></el-input></el-form-item><el-form-item label="设备名称" :label-width="formLabelWidth"><el-input v-model="deviceInfo.name" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="updateDeviceVisible = false">取 消</el-button><el-button type="primary" @click="updateDevice">确 定</el-button></div></el-dialog></div>
</template>
<script>import {getDeviceList, updateDevice,getCommandList,addCommand,deleteCommand,executeCommand} from '@/api/device'export default {name: 'device',data() {return {formLabelWidth: '140px',addCommandVisible: false,commandInfo: {name:"",commands: [{operation: '',param: '',delayTime: ''}]},operationOption: [{value: '单击',label: '单击'},{value: '返回',label: '返回'},{value: '右滑',label: '右滑'},{value: '截屏',label: '截屏'},{value: '点击Home键',label: '点击Home键'},{value: '卸载',label: '卸载'},{value: '输入文字',label: '输入文字'},{value: '左滑',label: '左滑'}],deviceListData: [],commandListData: [],deviceInfo: {sn: "",name: ""},executeParam:{devices:[],name:""},updateDeviceVisible:false,}},mounted() {this.getDeviceList()this.getCommandList()},methods: {selectDevices(val) {let selection = this.$refs.deviceTable.selection;this.executeParam.devices = []for (let item of selection){this.executeParam.devices.push(item.sn)}console.log(JSON.stringify(this.executeParam.devices))},getDeviceList() {getDeviceList().then(res => {if (res.code === 0) {this.deviceListData = res.data;} else {this.$message.error('查询失败!')}this.loading = false}).catch(err => {this.loading = falsethis.$message.error(err)})},operationChange(operation, index) {this.commandInfo.commands[index].operation = operation},editDevice(data){this.deviceInfo = datathis.updateDeviceVisible = true;},updateDevice() {updateDevice(this.deviceInfo).then(res => {if (res.code === 0) {this.getDeviceList()} else {this.$message.error('查询失败!')}this.loading = falsethis.updateDeviceVisible = false;}).catch(err => {this.loading = falsethis.$message.error(err)})},getCommandList() {getCommandList().then(res => {if (res.code === 0) {this.commandListData = res.data;} else {this.$message.error('查询失败!')}this.loading = false}).catch(err => {this.loading = falsethis.$message.error(err)})},addCommand() {addCommand(this.commandInfo).then(res => {if (res.code === 0) {this.getCommandList()} else {this.$message.error('命令添加失败!')}this.loading = falsethis.addCommandVisible = false;}).catch(err => {this.loading = falsethis.$message.error(err)})},updateCommand(data){this.addCommandVisible = true;this.commandInfo.name = data.namethis.commandInfo.commands = data.commands},deleteCommand(name){deleteCommand(name).then(res => {if (res.code === 0) {this.getCommandList()} else {this.$message.error('查询失败!')}this.loading = false}).catch(err => {this.loading = falsethis.$message.error(err)})},executeCommand(name){if (this.executeParam.devices.length === 0){this.$message.error('请先在左侧选择设备!')return}this.executeParam.name = nameexecuteCommand(this.executeParam).then(res => {if (res.code === 0) {this.$message.success('执行完成!')} else {this.$message.error('执行失败!')}this.loading = false}).catch(err => {this.loading = falsethis.$message.error(err)})},// 添加indextableRowClassName({row, rowIndex}) {row.index = rowIndex},// 添加操作addForm() {if (this.isDataComplete()) {this.commandInfo.commands.push({operation: '',param: '',delayTime: ''})} else {this.$message({message: '请完善信息后再添加',type: 'warning'})}},isDataComplete() {return this.commandInfo.commands.every((item) => item.operation)},// 删除操作removeIdx(item, index) {this.commandInfo.commands.splice(index, 1)this.$message({message: '删除成功',type: 'success'})}}}
</script>
<style scoped></style>

实际的效果可以看下视频演示

如何用电脑批量操作多部手机

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/839105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据挖掘与机器学习——机器学习概述

一、什么是机器学习 机器学习的英文名称叫Machine Learning&#xff0c;简称ML&#xff0c;该领域主要研究的是如何使计算机能够模拟人类的学习行为从而获得新的知识。 机器学习与数据挖掘的联系&#xff1a;简单来说&#xff0c;机器学习就是让计算机从大量 的数据中学习到相关…

yaml文件格式详解 及 k8s实战演示

目录 一 k8s 支持的语言格式 1&#xff0c;YAML 语法格式 2&#xff0c;查看 api 资源版本标签 二 k8s 运行nginx pod实例 yaml文件 具体讲解 1&#xff0c;写一个yaml文件demo 2&#xff0c;deployment 管理nginx 的yaml 文件 3&#xff0c;创建资源对象 4&#…

【四、性能测试】Linux stress 压力模拟测试工具

在做 CPU 问题解析之前&#xff0c;需要先了解一下压力模拟工具&#xff0c;可以将 CPU、MEM、IO 等进行压力模拟&#xff0c;可以在模拟压力的过程中进行问题解析 一、STRESS 模拟对CPU、Memory、IO、磁盘进行压力测试。可以使用 stress 工具&#xff0c;它是专门针对 linux…

mysql 多表关联查询性能优化-同一sql不同的执行计划

一、问题背景 相同的sql&#xff0c;不同的日期&#xff0c;执行的时间差异很大&#xff0c;执行计划不一样。执行快时&#xff0c;30ms左右。执行慢时&#xff0c;15s左右。 二、分析结论 1、经过分析&#xff0c;发现不同日期下&#xff0c;sql的执行计划不同&#xff0c;驱…

基于springboot+vue的学生考勤管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

实现mysql的主从复制、实现MySQL的读写分离与负载均衡

实验环境 &#xff08;注明&#xff09;以下的所有关于yum和rpm以及tar的软件需要自己准备&#xff0c;没有的话可以私信博主 实验目标&#xff1a; 1.实现mysql主从复制 2.实现mysql读写分离与负载均衡 实验一、搭建mysql主从复制 1.建立时间同步环境&#xff0c;在主节…

C++BuilderXE 如何让listView按文件名数字排序而非字母排序

int m_nDataColSort0; bool IsAsctrue; void __fastcall TForm1::RzListView4Compare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare) { if(m_nDataColSort0) { //按列表第二列排序 //CompareCompareText(Item1->SubItems-…

【MySQL精通之路】全文搜索-自然语言全文搜索

1.使用方法 默认情况下&#xff0c;或者使用IN NATURAL LANGUAGE MODE修饰符&#xff0c;MATCH&#xff08;&#xff09;函数对文本集合的字符串执行自然语言搜索。 1.1 集合 集合是FULLTEXT索引中包含的一个或多个列的集合。 1.2 搜索字符串 搜索字符串作为AGINST&#x…

高效定时器设计方案——层级时间轮

层级时间轮实现高性能定时器 此篇介绍时间轮&#xff0c;它的时间复杂度是最优的&#xff0c;插入、查找&#xff08;最小&#xff09;、删除都是O&#xff08;1&#xff09;&#xff0c;很恐怖的性能 这里示例一个三层时间轮&#xff0c;模拟时钟表盘的运作方式&#xff0c;…

力扣爆刷第142天之二叉树五连刷(构造树、搜索树)

力扣爆刷第142天之二叉树五连刷&#xff08;构造树、搜索树&#xff09; 文章目录 力扣爆刷第142天之二叉树五连刷&#xff08;构造树、搜索树&#xff09;一、106. 从中序与后序遍历序列构造二叉树二、654. 最大二叉树三、617. 合并二叉树四、700. 二叉搜索树中的搜索五、98. …

卷积神经网络(CNN)详细介绍及其原理详解

卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称CNN&#xff09;是深度学习中非常重要的一类神经网络&#xff0c;主要用于图像识别、图像分类、物体检测等计算机视觉任务。本文将详细介绍卷积神经网络的基本概念、结构组成及其工作原理&#xff0c;并…

每日一题Reverse Card (Easy Version)

文章目录 题名&#xff1a;题意&#xff1a;题解&#xff1a;代码&#xff1a; 题名&#xff1a; Reverse Card (Easy Version) 题意&#xff1a; 给定 n n n&#xff0c; m m m&#xff0c;存在 1 < a < n 1<a<n 1<a<n&#xff0c; 1 < b < m …

什么是网关鉴权及其在Spring Cloud Gateway中的实现

在现代微服务架构中&#xff0c;网关扮演着非常重要的角色&#xff0c;它是系统和外部世界之间的入口&#xff0c;负责路由请求、流量控制以及安全保护等任务。其中&#xff0c;网关鉴权是保障系统安全的重要环节之一。本文将深入介绍什么是网关鉴权&#xff0c;以及如何通过过…

BCD编码(8421)介绍

概念 BCD (Binary-Coded Decimal) 是一种二进制的数字编码形式&#xff0c;其特点每个十进制数位用4个二进制位来表示。 在网络IO中&#xff0c;你传输一个数字类型最少需要一字节&#xff0c;传输两个数字类型最少需要两字节&#xff0c;但是当你使用BCD编码后传输&#xff…

防静电液的这些用处你知道多少

防静电液又叫抗静电剂&#xff0c;是工业上常用来消除静电的化学用品&#xff0c;一般是液体状态&#xff0c;它的用途很广泛。 防静电液适用于对静电有控制要求的电器、仪器桌面、台面、塑料制品、包装品、存储盒、托盘、毛毯、织物等任何物品表面。 应用举例如消除各种塑胶材…

微服务中的鉴权怎么做?

大家好&#xff0c;我是苍何呀。 现在出去找工作&#xff0c;简历上不写上微服务的技术&#xff0c;仿佛自己跟不上时代了&#xff0c;面试官更是喜欢盯着微服务项目来提问。 但其实虽说微服务是主流&#xff0c;随着云原生架构的发展&#xff0c;微服务也是趋势&#xff0c;…

图论-最短路算法

1. Floyd算法 作用&#xff1a;用于求解多源最短路&#xff0c;可以求解出任意两点的最短路 利用动态规划只需三重循环即可&#xff08;动态规划可以把问题求解分为多个阶段&#xff09;定义dp[k][i][j]表示点i到点j的路径&#xff08;除去起点终点&#xff09;中最大编号不超…

算法题【面试准备】

算法题【面试准备】 前言推荐算法题NC72二叉树的镜像NC8:二叉树根节点到叶子节点和为指定值的路径NC9二叉树中是否存在节点和为指定值的路径NC14二叉树的之字形层序遍历[NC15 求二叉树的层序遍历](https://www.nowcoder.com/study/live/689/2/69)NC37:合并区间[NC111 最大数](h…

AI模型发展之路:开源还是闭源?

AI模型发展之路&#xff1a;开源还是闭源&#xff1f; 开源路径优势&#xff1a;发展前景&#xff1a; 闭源路径优势&#xff1a;发展前景&#xff1a; 一、自动化内容生成文章生成技术原理应用场景 视频生成技术原理应用场景 音频生成技术原理应用场景 二、内容分发与推广智能…

leetcode725-Split Linked List in Parts

题目 给你一个头结点为 head 的单链表和一个整数 k &#xff0c;请你设计一个算法将链表分隔为 k 个连续的部分。 每部分的长度应该尽可能的相等&#xff1a;任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。 这 k 个部分应该按照在链表中出现的顺序排列&…