python 几种android截屏方式的学习与使用

python 几种android截屏方式的学习与使用

screencap

screencap是Android的截屏工具。通过调用访问SurfaceFlinger服务或读取 /dev/graphics/fb0文件来实现屏幕截取。

方法:

  1. 直接获得图片的二进制数据,然后解析成相应的图片
	import subprocess
	import cv2
	import numpy as np
	
	def get_screenshot():
			# 使用subprocess的Popen调用adb shell命令,并将结果保存到PIPE管道中
	        process = subprocess.Popen('adb shell screencap -p', shell=True, stdout=subprocess.PIPE)
	        # 读取管道中的数据
	        screenshot = process.stdout.read()
	        # 将读取的字节流数据的回车换行替换成'\n'
	        binary_screenshot = screenshot.replace(b'\r\n', b'\n')
	        # 使用numpy和imdecode将二进制数据转换成cv2的mat图片格式
	        img_screenshot = cv2.imdecode(np.frombuffer(binary_screenshot, np.uint8), cv2.IMREAD_COLOR)
	
        return img_screenshot
  1. 将截图保存成png图片,然后pull到电脑端再读取
	import subprocess
	import cv2
	def adb(order):
	        return subprocess.Popen(order, shell=True, stdout=subprocess.PIPE, encoding='UTF-8').stdout
	
	def get_screenshot():
		adb('adb shell /system/bin/screencap -p /sdcard/screenshot.png') # 将截图保存到SDCard
        adb('adb pull /sdcard/screenshot.png ./screenshot.png')# 将截图从手机拉取到电脑
        adb('adb shell rm /sdcard/screenshot.png')# 删除手机端的截图
		
		image = cv2.imread('./screenshot.png') # 使用imread读取截图
		
		return image

appium

appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web应用和混合应用。
appium的安装就不在这里介绍了
关于appium安装配置时遇到的问题(传送门)

方法:

#-*- coding: UTF-8 -*-
import os
import time
import unittest
import base64
import numpy as np
import cv2
from appium import webdriver
# 用于路径的转换
PATH = lambda p: os.path.abspath(
    os.path.join(os.path.dirname(__file__), p)
)


desired_caps={}
desired_caps['platformName']='Android'
desired_caps['version']='6.0.0'
desired_caps['deviceName']='MI MAX 2'#这是测试机的型号,可以查看手机的关于本机选项获得

# desired_caps['app'] = PATH('mobileqq.apk')#被测试的App在电脑上的位置
# print(desired_caps['app'])
desired_caps['appPackage'] = 'com.tencent.mobileqq'
desired_caps['appActivity'] = 'com.tencent.mobileqq.activity.SplashActivity'
driver=webdriver.Remote('http://127.0.0.1:4725/wd/hub',desired_caps) # 访问端口,用于获取数据
time.sleep(3)

# 方法一:
# 使用appium的get_screenshot_as_flie(image_save_path),直接将图片数据保存早电脑端
# 然后通过cv2读取
while True:
    driver.get_screenshot_as_file(screen_save_path)
    start = time.clock()
    img = cv2.imread('./screenshot.png')
    cv2.imshow('test', img)
    cv2.waitKey(1)
    
# 方法二:
# 使用appium的get_screenshot_as_base64()获得截屏的数据流
# 然后通过base64解析数据格式
# 使用numpy再次转换成uint8格式
# 最后使用cv2自带的imdecode转换成mat格式
while(True):
    base64data = driver.get_screenshot_as_base64()
    imgData = base64.b64decode(base64data)
    nparr = np.fromstring(imgData,np.uint8)
    img = cv2.imdecode(nparr, 1)
    cv2.imshow('test', img)
    cv2.waitKey(1)

minicap

minicap是开源项目STF(Smartphone Test Farm)中的一个工具,负责屏幕显示。
minicap的配置也不介绍了,网上有很多

方法:

网上提供了很多种连续获取图片的方式,但是很多时候,在获取一张图片之后就马上需要对其进行处理,这样的情况连续获取图片的方式并不合适
但是由于minicap本身传输的设定,手机端的minicap会源源不断的想socket传输图片信息,导致再次通过socket获得图片时,并不一定是当前的图片信息
这个时候采用的是重新断开socket连接的方式来再次获得图片

# 连接端口
import socket
import cv2
import numpy as np  
  
def get_image()
	client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   	client_socket.connect(('localhost', 7777))

    readBannerBytes = 0
    bannerLength = 24
    readFrameBytes = 0
    frameBodyLengthRemaining = 0
    frameBody = ''
    while True:
        chunk = self.client_socket.recv(12000)
        if len(chunk) == 0:
            continue
        cursor = 0
        while cursor < len(chunk):
        	 # 跳过前面24位baner信息 
            if (readBannerBytes < bannerLength):
                cursor += 1
                readBannerBytes += 1
               
            elif readFrameBytes < 4: # 在一开始的24位baner信息之后就是4位图片长度的信息
                frameBodyLengthRemaining += (int(hex(chunk[cursor]), 16) << (readFrameBytes * 8))
                cursor += 1
                readFrameBytes += 1
            else:
                # 如果当前剩下的数据长度超过了图片还未读取的长度,说明这里包含了下一张图片的信息(由于不是连续读取,所以不考虑这些信息)
                if len(chunk) - cursor >= frameBodyLengthRemaining:
                    frameBody = frameBody + chunk[cursor:(cursor + frameBodyLengthRemaining)]
                    if hex(frameBody[0]) != '0xff' or hex(frameBody[1]) != '0xd8':
                        exit()
                    img = np.array(bytearray(frameBody))
                    img = cv2.imdecode(img, 1)
                    self.client_socket.close()
                    return img
                else:
                	 # 这次数据的读取还未达到图片的数据的长度 
                    frameBody = bytes(list(frameBody) + list(chunk[cursor:len(chunk)]))
                    frameBodyLengthRemaining -= (len(chunk) - cursor)
                    readFrameBytes += len(chunk) - cursor
                    cursor = len(chunk)

if __name__ == '__main__':
	image = get_image()

你可能感兴趣的:(python,自动化测试)