python 使用 adb 截屏

第一版:

  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个字节,确定还是存在回车换行的问题,还是需要进行转换。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值