第一版:
adb_cmd.adb_cmd("shell screencap -p /data/local/tmp/tmp.png")
time.sleep(0.2)
adb_cmd.adb_cmd("pull /data/local/tmp/tmp.png " + path)
time.sleep(1)
adb_cmd.adb_cmd("shell rm /data/local/tmp/tmp.png")
具体过程是先截屏保存在手机中,在使用pull指令保存到本地,这样做比较耗时,考虑优化;
使用管道直接存到本地,去掉保存在手机中的过程;
第二版:
if device is None:
cmd = f'adb shell screencap -p > {tmp}'
else:
cmd = f'adb -s {device} shell screencap -p > {tmp}'
ret = os.popen(cmd)
使用管道重定向直接存在本地,但这样保存的图片不能直接使用,直接对比文件:
上图是正常的图片文件,下图是异常的图片文件,可以看出所有0a都转换成了0d 0a,当作文本格式自动将换行符转换成回车换行了;重新转换回来:
file = open(tmp, 'rb')
find = False
for i in range(size):
data = file.read(1)
if data == '': break
if find:
if data != b'\n':
w.write(b'\r')
find = False
if data == b'\r':
find = True
continue
w.write(data)
运行发现转换后的图片不全,判断是截图指令还未执行完毕,判断临时文件长度没有变化才开始转换
l = 0
c = 0
while True:
size = os.path.getsize(tmp)
if size != 0 and size == l: break
l = size
c += 1
if c > 10: break
time.sleep(0.2)
完整第二版代码:
tmp = path_name('tmp',0)
if device is None:
cmd = f'adb shell screencap -p > {tmp}'
else:
cmd = f'adb -s {device} shell screencap -p > {tmp}'
print(cmd,end='...')
w = open(path, 'wb')
ret = os.popen(cmd)
time.sleep(1)
l = 0
c = 0
while True:
size = os.path.getsize(tmp)
if size != 0 and size == l: break
l = size
c += 1
if c > 10: break
time.sleep(0.2)
print(c,size)
file = open(tmp, 'rb')
find = False
for i in range(size):
data = file.read(1)
if data == '': break
if find:
if data != b'\n':
w.write(b'\r')
find = False
if data == b'\r':
find = True
continue
w.write(data)
w.close()
file.close()
print(path)
#time.sleep(1)
return path
相较第一版,速度有较大的提升,但感觉还是不太理想,图片数据临时保存到硬盘上,再读入处理,效率还是有点低,可否直接在内存中处理,去掉保存临时文件的步骤。尝试过直接读取popen管道数据,但是会报编码错误;在网上一通查找,找到subprocess.Popen方法;
第三版代码:
cmd = []
cmd.append('adb')
device = sqlite.get_device()
if not device is None:
cmd.append('-s')
cmd.append(device)
cmd.append('shell')
cmd.append('screencap')
cmd.append('-p')
print(cmd,end='...')
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
#p.wait()
output = p.communicate()[0]
#print(output)
size = len(output)
print('size',size)
#file = open(tmp, 'rb')
w = open(path, 'wb')
find = False
c = 0
for i in range(size):
data = output[i].to_bytes(1,byteorder='little', signed=False) #file.read(1)
if c < 10:
print(data,end=' ')
c += 1
if data == '': break
if find:
if data != b'\n':
w.write(b'\r')
find = False
if data == b'\r':
find = True
continue
w.write(data)
w.close()
感觉这个方法是最优的了,有两个地方需要注意:
output = p.communicate()[0]
p.communicate()返回的是数组,第一项才是输出;
data = output[i].to_bytes(1,byteorder='little', signed=False)
返回的是int类型数组,需要转换成byte
if c < 10:
print(data,end=' ')
打印了前10个字节,确定还是存在回车换行的问题,还是需要进行转换。