安卓自动化之minicap截图

安卓自动化之minicap截图

关于安卓自动化使用找图方法点击时,最大的痛点是使用原生adb截图速度太慢了,大概需要3s的时间,再加上我们使用opencv的找图算法,时间就去都三秒多了,为了解决这一个痛点,我们就可以使用minicap,他是通过在安卓常驻一个miniservice,通过adb跟我们的程序进行通信,它实时获取屏幕信息转化为数据流发送给我们的程序,我们只需实时去接收数据并把它转化成图片即可
1.第一步当然是先在安卓上安装我们的miniservice

pip install uiautomator2 
python -m uiautomator2 init 
or
import uiautomator2 as u2
device =u2.connect()

我们在初始化的时候或者使用uiautomator2时会默认安装适合我们安卓架构的minicapservice
2.第二部使用adb命令启动安卓中的minicapservice

adb forward tcp:1717 localabstract:minicap
adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 6480x960@6480x960/0

6480x960@6480x960 是我们安卓设备的屏幕像素

adb shell wn size

3.第三步,编写接收数据,并转换成图片

import socket
import sys
import struct
from collections import OrderedDictclass Banner:def __init__(self):self.__banner = OrderedDict([('version', 0),('length', 0),('pid', 0),('realWidth', 0),('realHeight', 0),('virtualWidth', 0),('virtualHeight', 0),('orientation', 0),('quirks', 0)])def __setitem__(self, key, value):self.__banner[key] = valuedef __getitem__(self, key):return self.__banner[key]def keys(self):return self.__banner.keys()def __str__(self):return str(self.__banner)class MiniCap:def __init__(self, host, port, banner):self.buffer_size = 4096self.host = hostself.port = portself.banner = bannerself.socket = Noneself.stop_flag = Falsedef connect(self):"""Connect to the specified host and port.Raises:socket.error: If there is any error creating the socket or connecting."""try:self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.socket.connect((self.host, self.port))except socket.error as e:print(f"Failed to connect to {self.host}:{self.port}. Error: {e}")raise e@classmethoddef save_image(cls, data):file_name = 'received_image.jpg'  # 图片名with open(file_name, 'wb') as f:for b in data:f.write(b.to_bytes(1, 'big'))def consume(self,stop_flag):readBannerBytes = 0bannerLength = 24readFrameBytes = 0frameBodyLength = 0data = []while not stop_flag:try:chunk = self.socket.recv(self.buffer_size)except socket.error as e:print(e)sys.exit(1)cursor = 0buf_len = len(chunk)while cursor < buf_len:if readBannerBytes < bannerLength:map(lambda i, val: self.banner.__setitem__(self.banner.keys()[i], val),[i for i in range(len(self.banner.keys()))], struct.unpack("<2b5ibB", chunk))cursor = buf_lenreadBannerBytes = bannerLengthelif readFrameBytes < 4:frameBodyLength += (chunk[cursor] << (readFrameBytes * 8)) >> 0cursor += 1readFrameBytes += 1else:if buf_len - cursor >= frameBodyLength:data.extend(chunk[cursor:cursor + frameBodyLength])self.save_image(data)cursor += frameBodyLengthframeBodyLength = readFrameBytes = 0data = []else:data.extend(chunk[cursor:buf_len])frameBodyLength -= buf_len - cursorreadFrameBytes += buf_len - cursorcursor = buf_lendef run(self,stop_flag):"""Connect to the specified host and port, then consume all frames from the socket.Raises:socket.error: If there is any error creating the socket or connecting."""try:self.connect()self.consume(stop_flag)except socket.error as e:print(f"Failed to connect to {self.host}:{self.port}. Error: {e}")raise eif '__main__' == __name__:# time.sleep(1)mc = MiniCap('localhost', 1717, Banner())mc.run(True)

当我们运行程序的时候就会在当前目录生成一个图片received_image.jpg,这个时候我们就完成了截图啦,但是这个图片实时更新的我们的其他程序是没有办法去读取图片的,这个时候就需要我们去截图啦,什么还要去截图,太麻烦了吧,不,准确的来说只是copy一下啦,截图就是copy一下,谁能有我截图快,快如电,嗖嗖嗖的

  def mini_cap_screen(self, local_path, time_out):"""mini cap截图Args:local_path: 目标路径time_out: 超时时间(秒)Returns:local_path 或 None"""src_path = "received_image.jpg"end_time = datetime.now() + timedelta(seconds=time_out)start_time = datetime.now()self.logger.info(f"mini cap 截图开始时间: {start_time}")while datetime.now() < end_time:if os.path.exists(src_path) and os.path.getsize(src_path) > 200000:os.makedirs(os.path.dirname(local_path), exist_ok=True)shutil.copy2(src_path, local_path)self.logger.info(f"Image copied to {local_path}")current_time = datetime.now()self.logger.info(f"mini cap 截图结束时间: {current_time}")self.logger.info(f"mini cap 截图耗时: {current_time - start_time}")return local_pathtime.sleep(0.1)self.logger.error("mini cap 截图失败,请检测mini cap service is running")return None

本人天下第一快,NO,我说的是程序,经过计算我们截图加opencv找图然后在模拟点击只需250毫秒,嘎嘎快

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

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

相关文章

HBase数据库面试知识点:第二部分 - 核心技术(持续更新中)

目录 1. 分布式存储与HDFS 2. 面向列的存储 3. 数据版本控制 4. Region与RegionServer 5. 分布式协调服务&#xff08;ZooKeeper&#xff09; 1. 分布式存储与HDFS HBase利用Hadoop的HDFS作为其底层存储系统&#xff0c;确保数据的高可靠性和可扩展性。 数据块&#xff0…

Python爬虫如何入门:一步步走向精通的指南

Python爬虫如何入门&#xff1a;一步步走向精通的指南 在信息爆炸的时代&#xff0c;爬虫技术已经成为获取、整理和分析数据的必备技能。Python&#xff0c;以其简洁易懂的语法和强大的库支持&#xff0c;成为了爬虫开发的热门语言。那么&#xff0c;如何入门Python爬虫呢&…

研发质量测试工程师的笔试题

研发质量测试工程师的笔试题通常会考察候选人在测试理论、测试方法、测试工具使用以及实际案例分析等方面的知识和能力。以下是一些可能出现在研发质量测试工程师笔试中的题目类型和内容&#xff1a; 一、测试理论题 请简述软件测试的目的和基本原则。描述黑盒测试和白盒测试…

Python | 句子缩写

字符串大小的比较Unicode码值 类似于asc|| 码 小写字母从 a 到 z 对应的 Unicode 码值是从 97 到 122&#xff0c;而大写字母从 A 到 Z 对应的 Unicode 码值是从 65 到 90, 大小写字母之间的差值为32&#xff0c;所以可以通过数学运算将小写字符减去32后转换为大写字符。 字…

26、matlab多项式曲线拟合:polyfit ()函数

1、polyfit 多项式曲线拟合 语法 语法&#xff1a;p polyfit(x,y,n) 返回次数为 n 的多项式 p(x) 的系数&#xff0c;该阶数是 y 中数据的最佳拟合&#xff08;基于最小二乘指标&#xff09;。 语法&#xff1a;[p,S] polyfit(x,y,n) 还返回一个结构体 S 语法&#xff1a;[…

优化 mac 储存空间的方法 只需一招为你的苹果电脑提速

在职场中&#xff0c;许多人都对苹果电脑情有独钟。苹果电脑以其简洁美观的设计、流畅稳定的性能以及出色的用户体验&#xff0c;成为了众多职场人士的得力助手。无论是处理文档、制作演示文稿&#xff0c;还是进行创意设计等工作&#xff0c;苹果电脑都能展现出其独特的优势&a…

微信小程序公众号二合一分销商城源码系统 基于PHP+MySQL组合开发的 可多商户商家入驻 带完整的安装代码包以及搭建教程

系统概述 微信小程序公众号二合一分销商城源码系统&#xff0c;是基于PHPMySQL组合开发的一款高效、稳定的电子商务平台解决方案。该系统创新性地将微信公众号与小程序的功能进行了深度整合&#xff0c;为商家提供了一个功能齐全、易于管理的分销商城系统。通过此系统&#xf…

Vue3+vant 带你实现常见的历史记录的业务功能

前言 大部分小伙伴不管是开发PC端还是H5移动端&#xff0c;都会遇到历史搜索的功能。对用户的历史记录进行增删查可以是接口&#xff0c;也可以是前端用缓存实现&#xff0c;一般用浏览器缓存实现的比较多&#xff0c;这篇文章就来教你如何用LocalStorage对历史记录数据的存储、…

视创云展元宇宙虚拟展厅,带来沉浸式的逛展体验!

近年来&#xff0c;随着科技的飞速发展和市场需求的不断演变&#xff0c;众多企业纷纷将目光转向线上虚拟展厅的建设。视创云展元宇宙虚拟展厅凭借其创新性和实用性&#xff0c;为众多企业带来了前所未有的宣传体验&#xff0c;成为了商企展示自我、推广产品的全新舞台。 与传统…

Java 生成SSL证书

第一步&#xff1a; cmd打开指令窗口 第二步&#xff1a; 运行指令&#xff1a; keytool -keystore hk.jks -storepass 123456 -deststoretype jks -genkeypair -keyalg RSA -validity 365 -alias contrastserver -dname "CN111.230.63.59, OUHK, OHK, LZH, STGD, CCN&…

XSKY对象存储深度结合Alluxio分布式缓存系统,GPU利用率提高至90%以上

近日&#xff0c;Alluxio分布式缓存系统完成了与XSKY星辰天合的 XEOS V6.4 对象存储的兼容性测试&#xff0c;旨在解决数据管理和加速方面的挑战。双方进行了深度的产品对接和联合开发&#xff0c;将 Alluxio 分布式缓存系统与 XEOS 对象存储的众多应用特性进行结合&#xff0c…

MySQL学习——INFORMATION_SCHEMA触发器表

TRIGGERS表提供了有关触发器的信息。要查看有关表触发器的信息&#xff0c;必须具有该表的TRIGGER权限。 TRIGGERS表包含以下列&#xff1a; TRIGGER_CATALOG&#xff1a;触发器所属的目录名称。此值始终为def。 TRIGGER_SCHEMA&#xff1a;触发器所属的架构&#xff08;数据…

工厂模式 使用全局变量自己注册

前言 使用工厂模式时&#xff0c;需要将类注册进工厂里&#xff0c;看到一种新的奇技淫巧&#xff0c;使用静态变量来将类注册进工厂。代码 Product.h #ifndef PRODUCT_H #define PRODUCT_Hclass Product { public:Product(){};virtual ~Product(){};virtual void doWork() …

38. 【Java教程】日期和时间处理

本小节我们将学习 Java 中的日期和时间&#xff0c;日期和时间在我们的实际开发中非常常用&#xff0c;例如用户的注册、数据的增删改、对敏感信息的操作等等都需要记录下日期和时间。通过本小节的学习&#xff0c;你将了解到什么是日期、什么是时间、什么是时区&#xff0c;Ja…

分享一个fpga任意分频的代码

分享一个fpga任意分频的代码&#xff0c;非50%占空比的分频代码&#xff0c; 这里以16以内 的分频为例 module clkdiv #(parameter div 4)(input clk,input rst,//input [3:0] div,output reg clk_div );//reg …

3072. 将元素分配到两个数组中 II

题目 给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 现定义函数 greaterCount &#xff0c;使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。 你需要使用 n 次操作&#xff0c;将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操…

Mysql间隙锁死锁避免最佳实践

最近写代码的时候听说&#xff0c;批量操作提高死锁的概率&#xff0c;但是心里又想&#xff0c;为什么没看到任何一款数据库相关的中间价禁止或者提醒批量操作&#xff1f;心里想肯定是因为一起其他操作的不当导致的死锁问题。进行了一些思考&#xff0c;希望可以帮助到大家 …

WebGL画粗线

目录 前言 基本思路 求左右端点 实现 组织数据 顶点着色器计算端点坐标 效果 前言 WebGL绘制模式有点、线、面三种&#xff1b;通过点的绘制可以实现粒子系统等&#xff0c;通过线可以绘制一些连线关系&#xff1b;面就强大了&#xff0c;通过面&#xff0c;我们可以…

视频监控汇聚平台LntonCVS国标GB28181协议实现语音对讲功能

在当今这个智能技术飞速发展的时代&#xff0c;人工智能已经成为了电子产品领域的一股不可忽视的热门趋势。随着科技的不断进步&#xff0c;越来越多的电子产品开始融入人工智能技术&#xff0c;从而为其开拓了全新的发展路径。在这个大背景下&#xff0c;安防摄像头无插件直播…

什么叫硬编码?如何避免硬编码

硬编码&#xff08;Hardcoding或Hard-coding&#xff09;是指在编写程序时&#xff0c;直接将具体的值&#xff08;如字符串、数字、路径等&#xff09;写入源代码中&#xff0c;而不是通过变量、配置文件、数据库查询或其他动态方法来获取这些值。这种方式虽然简单直接&#x…