1. 程式人生 > 程式設計 >Python實現對adb命令封裝

Python實現對adb命令封裝

我就廢話不多說了,大家還是直接看程式碼吧!

#!/usr/bin/evn python
# -*- coding:utf-8 -*-
 
# FileName adbtools.py
# Author: HeyNiu
# Created Time: 2016/9/19
"""
adb 工具類
"""
 
import os
import platform
import re
import time
import utils.timetools
 
 
class AdbTools(object):
 
  def __init__(self,device_id=''):
    self.__system = platform.system()
    self.__find = ''
    self.__command = ''
    self.__device_id = device_id
    self.__get_find()
    self.__check_adb()
    self.__connection_devices()
 
  def __get_find(self):
    """
    判斷系統型別,windows使用findstr,linux使用grep
    :return:
    """
    if self.__system is "Windows":
      self.__find = "findstr"
    else:
      self.__find = "grep"
 
  def __check_adb(self):
    """
    檢查adb
    判斷是否設定環境變數ANDROID_HOME
    :return:
    """
    if "ANDROID_HOME" in os.environ:
      if self.__system == "Windows":
        path = os.path.join(os.environ["ANDROID_HOME"],"platform-tools","adb.exe")
        if os.path.exists(path):
          self.__command = path
        else:
          raise EnvironmentError(
            "Adb not found in $ANDROID_HOME path: %s." % os.environ["ANDROID_HOME"])
      else:
        path = os.path.join(os.environ["ANDROID_HOME"],"adb")
        if os.path.exists(path):
          self.__command = path
        else:
          raise EnvironmentError(
            "Adb not found in $ANDROID_HOME path: %s." % os.environ["ANDROID_HOME"])
    else:
      raise EnvironmentError(
        "Adb not found in $ANDROID_HOME path: %s." % os.environ["ANDROID_HOME"])
 
  def __connection_devices(self):
    """
    連線指定裝置,單個裝置可不傳device_id
    :return:
    """
    if self.__device_id == "":
      return
    self.__device_id = "-s %s" % self.__device_id
 
  def adb(self,args):
    """
    執行adb命令
    :param args:引數
    :return:
    """
    cmd = "%s %s %s" % (self.__command,self.__device_id,str(args))
    # print(cmd)
    return os.popen(cmd)
 
  def shell(self,args):
    """
    執行adb shell命令
    :param args:引數
    :return:
    """
    cmd = "%s %s shell %s" % (self.__command,str(args))
    # print(cmd)
    return os.popen(cmd)
 
  def mkdir(self,path):
    """
    建立目錄
    :param path: 路徑
    :return:
    """
    return self.shell('mkdir %s' % path)
 
  def get_devices(self):
    """
    獲取裝置列表
    :return:
    """
    l = self.adb('devices').readlines()
    return (i.split()[0] for i in l if 'devices' not in i and len(i) > 5)
 
  def get_current_application(self):
    """
    獲取當前執行的應用資訊
    :return:
    """
    return self.shell('dumpsys window w | %s \/ | %s name=' % (self.__find,self.__find)).read()
 
  def get_current_package(self):
    """
    獲取當前執行app包名
    :return:
    """
    reg = re.compile(r'name=(.+?)/')
    return re.findall(reg,self.get_current_application())[0]
 
  def get_current_activity(self):
    """
    獲取當前執行activity
    :return: package/activity
    """
    reg = re.compile(r'name=(.+?)\)')
    return re.findall(reg,self.get_current_application())[0]
 
  def __get_process(self,package_name):
    """
    獲取程序資訊
    :param package_name:
    :return:
    """
    if self.__system is "Windows":
      pid_command = self.shell("ps | %s %s$" % (self.__find,package_name)).read()
    else:
      pid_command = self.shell("ps | %s -w %s" % (self.__find,package_name)).read()
    return pid_command
 
  def process_exists(self,package_name):
    """
    返回程序是否存在
    :param package_name:
    :return:
    """
    process = self.__get_process(package_name)
    return package_name in process
 
  def get_pid(self,package_name):
    """
    獲取pid
    :return:
    """
    pid_command = self.__get_process(package_name)
    if pid_command == '':
      print("The process doesn't exist.")
      return pid_command
 
    req = re.compile(r"\d+")
    result = str(pid_command).split()
    result.remove(result[0])
    return req.findall(" ".join(result))[0]
 
  def get_uid(self,pid):
    """
    獲取uid
    :param pid:
    :return:
    """
    result = self.shell("cat /proc/%s/status" % pid).readlines()
    for i in result:
      if 'uid' in i.lower():
        return i.split()[1]
 
  def get_flow_data_tcp(self,uid):
    """
    獲取應用tcp流量
    :return:(接收,傳送)
    """
    tcp_rcv = self.shell("cat proc/uid_stat/%s/tcp_rcv" % uid).read().split()[0]
    tcp_snd = self.shell("cat proc/uid_stat/%s/tcp_snd" % uid).read().split()[0]
    return tcp_rcv,tcp_snd
 
  def get_flow_data_all(self,uid):
    """
    獲取應用流量全部資料
    包含該應用多個程序的所有資料 tcp udp等
    (rx_bytes,tx_bytes) >> (接收,傳送)
    :param uid:
    :return:list(dict)
    """
    all_data = []
    d = {}
    data = self.shell("cat /proc/net/xt_qtaguid/stats | %s %s" % (self.__find,uid)).readlines()
    for i in data:
      if not i.startswith('\n'):
        item = i.strip().split()
        d['idx'] = item[0]
        d['iface'] = item[1]
        d['acct_tag_hex'] = item[2]
        d['uid_tag_int'] = item[3]
        d['cnt_set'] = item[4]
        d['rx_bytes'] = item[5]
        d['rx_packets'] = item[6]
        d['tx_bytes'] = item[7]
        d['tx_packets'] = item[8]
        d['rx_tcp_bytes'] = item[9]
        d['rx_tcp_packets'] = item[10]
        d['rx_udp_bytes'] = item[11]
        d['rx_udp_packets'] = item[12]
        d['rx_other_bytes'] = item[13]
        d['rx_other_packets'] = item[14]
        d['tx_tcp_bytes'] = item[15]
        d['tx_tcp_packets'] = item[16]
        d['tx_udp_bytes'] = item[17]
        d['tx_udp_packets'] = item[18]
        d['tx_other_bytes'] = item[19]
        d['tx_other_packets'] = item[20]
 
        all_data.append(d)
        d = {}
    return all_data
 
  @staticmethod
  def dump_apk(path):
    """
    dump apk檔案
    :param path: apk路徑
    :return:
    """
    # 檢查build-tools是否新增到環境變數中
    # 需要用到裡面的aapt命令
    l = os.environ['PATH'].split(';')
    build_tools = False
    for i in l:
      if 'build-tools' in i:
        build_tools = True
    if not build_tools:
      raise EnvironmentError("ANDROID_HOME BUILD-TOOLS COMMAND NOT FOUND.\nPlease set the environment variable.")
    return os.popen('aapt dump badging %s' % (path,))
 
  @staticmethod
  def dump_xml(path,filename):
    """
    dump apk xml檔案
    :return:
    """
    return os.popen('aapt dump xmlstrings %s %s' % (path,filename))
 
  def uiautomator_dump(self):
    """
    獲取螢幕uiautomator xml檔案
    :return:
    """
    return self.shell('uiautomator dump').read().split()[-1]
 
  def pull(self,source,target):
    """
    從手機端拉取檔案到電腦端
    :return:
    """
    self.adb('pull %s %s' % (source,target))
 
  def push(self,target):
    """
    從電腦端推送檔案到手機端
    :param source:
    :param target:
    :return:
    """
    self.adb('push %s %s' % (source,target))
 
  def remove(self,path):
    """
    從手機端刪除檔案
    :return:
    """
    self.shell('rm %s' % (path,))
 
  def clear_app_data(self,package):
    """
    清理應用資料
    :return:
    """
    self.shell('pm clear %s' % (package,))
 
  def install(self,path):
    """
    安裝apk檔案
    :return:
    """
    # adb install 安裝錯誤常見列表
    errors = {'INSTALL_FAILED_ALREADY_EXISTS': '程式已經存在','INSTALL_DEVICES_NOT_FOUND': '找不到裝置','INSTALL_FAILED_DEVICE_OFFLINE': '裝置離線','INSTALL_FAILED_INVALID_APK': '無效的APK','INSTALL_FAILED_INVALID_URI': '無效的連結','INSTALL_FAILED_INSUFFICIENT_STORAGE': '沒有足夠的儲存空間','INSTALL_FAILED_DUPLICATE_PACKAGE': '已存在同名程式','INSTALL_FAILED_NO_SHARED_USER': '要求的共享使用者不存在','INSTALL_FAILED_UPDATE_INCOMPATIBLE': '版本不能共存','INSTALL_FAILED_SHARED_USER_INCOMPATIBLE': '需求的共享使用者簽名錯誤','INSTALL_FAILED_MISSING_SHARED_LIBRARY': '需求的共享庫已丟失','INSTALL_FAILED_REPLACE_COULDNT_DELETE': '需求的共享庫無效','INSTALL_FAILED_DEXOPT': 'dex優化驗證失敗','INSTALL_FAILED_DEVICE_NOSPACE': '手機儲存空間不足導致apk拷貝失敗','INSTALL_FAILED_DEVICE_COPY_FAILED': '檔案拷貝失敗','INSTALL_FAILED_OLDER_SDK': '系統版本過舊','INSTALL_FAILED_CONFLICTING_PROVIDER': '存在同名的內容提供者','INSTALL_FAILED_NEWER_SDK': '系統版本過新','INSTALL_FAILED_TEST_ONLY': '呼叫者不被允許測試的測試程式','INSTALL_FAILED_CPU_ABI_INCOMPATIBLE': '包含的本機程式碼不相容','CPU_ABIINSTALL_FAILED_MISSING_FEATURE': '使用了一個無效的特性','INSTALL_FAILED_CONTAINER_ERROR': 'SD卡訪問失敗','INSTALL_FAILED_INVALID_INSTALL_LOCATION': '無效的安裝路徑','INSTALL_FAILED_MEDIA_UNAVAILABLE': 'SD卡不存在','INSTALL_FAILED_INTERNAL_ERROR': '系統問題導致安裝失敗','INSTALL_PARSE_FAILED_NO_CERTIFICATES': '檔案未通過認證 >> 設定開啟未知來源','INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES': '檔案認證不一致 >> 先解除安裝原來的再安裝','INSTALL_FAILED_INVALID_ZIP_FILE': '非法的zip檔案 >> 先解除安裝原來的再安裝','INSTALL_CANCELED_BY_USER': '需要使用者確認才可進行安裝','INSTALL_FAILED_VERIFICATION_FAILURE': '驗證失敗 >> 嘗試重啟手機','DEFAULT': '未知錯誤'
         }
    print('Installing...')
    l = self.adb('install -r %s' % (path,)).read()
    if 'Success' in l:
      print('Install Success')
    if 'Failure' in l:
      reg = re.compile('\\[(.+?)\\]')
      key = re.findall(reg,l)[0]
      try:
        print('Install Failure >> %s' % errors[key])
      except KeyError:
        print('Install Failure >> %s' % key)
    return l
 
  def uninstall(self,package):
    """
    解除安裝apk
    :param package: 包名
    :return:
    """
    print('Uninstalling...')
    l = self.adb('uninstall %s' % (package,)).read()
    print(l)
 
  def screenshot(self,target_path=''):
    """
    手機截圖
    :param target_path: 目標路徑
    :return:
    """
    format_time = utils.timetools.timestamp('%Y%m%d%H%M%S')
    self.shell('screencap -p /sdcard/%s.png' % (format_time,))
    time.sleep(1)
    if target_path == '':
      self.pull('/sdcard/%s.png' % (format_time,),os.path.expanduser('~'))
    else:
      self.pull('/sdcard/%s.png' % (format_time,target_path)
    self.remove('/sdcard/%s.png' % (format_time,))
 
  def get_cache_logcat(self):
    """
    匯出快取日誌
    :return:
    """
    return self.adb('logcat -v time -d')
 
  def get_crash_logcat(self):
    """
    匯出崩潰日誌
    :return:
    """
    return self.adb('logcat -v time -d | %s AndroidRuntime' % (self.__find,))
 
  def clear_cache_logcat(self):
    """
    清理快取區日誌
    :return:
    """
    self.adb('logcat -c')
 
  def get_device_time(self):
    """
    獲取裝置時間
    :return:
    """
    return self.shell('date').read().strip()
 
  def ls(self,command):
    """
    shell ls命令
    :return:
    """
    return self.shell('ls %s' % (command,)).readlines()
 
  def file_exists(self,target):
    """
    判斷檔案在目標路徑是否存在
    :return:
    """
    l = self.ls(target)
    for i in l:
      if i.strip() == target:
        return True
    return False
 
  def is_install(self,target_app):
    """
    判斷目標app在裝置上是否已安裝
    :param target_app: 目標app包名
    :return: bool
    """
    return target_app in self.shell('pm list packages %s' % (target_app,)).read()
 
  def get_device_model(self):
    """
    獲取裝置型號
    :return:
    """
    return self.shell('getprop ro.product.model').read().strip()
 
  def get_device_id(self):
    """
    獲取裝置id
    :return:
    """
    return self.adb('get-serialno').read().strip()
 
  def get_device_android_version(self):
    """
    獲取裝置Android版本
    :return:
    """
    return self.shell('getprop ro.build.version.release').read().strip()
 
  def get_device_sdk_version(self):
    """
    獲取裝置SDK版本
    :return:
    """
    return self.shell('getprop ro.build.version.sdk').read().strip()
 
  def get_device_mac_address(self):
    """
    獲取裝置MAC地址
    :return:
    """
    return self.shell('cat /sys/class/net/wlan0/address').read().strip()
 
  def get_device_ip_address(self):
    """
    獲取裝置IP地址
    pass: 適用WIFI 蜂窩資料
    :return:
    """
    if not self.get_wifi_state() and not self.get_data_state():
      return
    l = self.shell('ip addr | %s global' % self.__find).read()
    reg = re.compile('\d+\.\d+\.\d+\.\d+')
    return re.findall(reg,l)[0]
 
  def get_device_imei(self):
    """
    獲取裝置IMEI
    :return:
    """
    sdk = self.get_device_sdk_version()
    # Android 5.0以下方法
    if int(sdk) < 21:
      l = self.shell('dumpsys iphonesubinfo').read()
      reg = re.compile('[0-9]{15}')
      return re.findall(reg,l)[0]
    elif self.root():
      l = self.shell('service call iphonesubinfo 1').read()
      print(l)
      print(re.findall(re.compile("'.+?'"),l))
      imei = ''
      for i in re.findall(re.compile("'.+?'"),l):
        imei += i.replace('.','').replace("'",'').replace(' ','')
      return imei
    else:
      print('The device not root.')
      return ''
 
  def check_sim_card(self):
    """
    檢查裝置SIM卡
    :return:
    """
    return len(self.shell('getprop | %s gsm.operator.alpha]' % self.__find).read().strip().split()[-1]) > 2
 
  def get_device_operators(self):
    """
    獲取運營商
    :return:
    """
    return self.shell('getprop | %s gsm.operator.alpha]' % self.__find).read().strip().split()[-1]
 
  def get_device_state(self):
    """
    獲取裝置狀態
    :return:
    """
    return self.adb('get-state').read().strip()
 
  def get_display_state(self):
    """
    獲取螢幕狀態
    :return: 亮屏/滅屏
    """
    l = self.shell('dumpsys power').readlines()
    for i in l:
      if 'mScreenOn=' in i:
        return i.split()[-1] == 'mScreenOn=true'
      if 'Display Power' in i:
        return 'ON' in i.split('=')[-1].upper()
 
  def get_screen_normal_size(self):
    """
    獲取裝置螢幕解析度 >> 標配
    :return:
    """
    return self.shell('wm size').read().strip().split()[-1].split('x')
 
  def get_screen_reality_size(self):
    """
    獲取裝置螢幕解析度 >> 實際解析度
    :return:
    """
    x = 0
    y = 0
    l = self.shell(r'getevent -p | %s -e "0"' % self.__find).readlines()
    for n in l:
      if len(n.split()) > 0:
        if n.split()[0] == '0035':
          x = int(n.split()[7].split(',')[0])
        elif n.split()[0] == '0036':
          y = int(n.split()[7].split(',')[0])
    return x,y
 
  def get_device_interior_sdcard(self):
    """
    獲取內部SD卡空間
    :return: (path,total,used,free,block)
    """
    return self.shell('df | %s \/mnt\/shell\/emulated' % self.__find).read().strip().split()
 
  def get_device_external_sdcard(self):
    """
    獲取外部SD卡空間
    :return: (path,block)
    """
    return self.shell('df | %s \/storage' % self.__find).read().strip().split()
 
  def __fill_rom(self,path,stream,count):
    """
    填充資料
    :param path: 填充地址
    :param stream: 填充流大小
    :param count: 填充次數
    :return:
    """
    self.shell('dd if=/dev/zero of=%s bs=%s count=%s' % (path,count)).read().strip()
 
  def fill_interior_sdcard(self,filename,size):
    """
    填充內建SD卡
    :param filename: 檔名
    :param size: 填充大小,單位byte
    :return:
    """
    if size > 10485760: # 10m
      self.__fill_rom('sdcard/%s' % filename,10485760,size / 10485760)
    else:
      self.__fill_rom('sdcard/%s' % filename,size,1)
 
  def fill_external_sdcard(self,size):
    """
    填充外接SD卡
    :param filename: 檔名
    :param size: 填充大小,單位byte
    :return:
    """
    path = self.get_device_external_sdcard()[0]
    if size > 10485760: # 10m
      self.__fill_rom('%s/%s' % (path,filename),size / 10485760)
    else:
      self.__fill_rom('%s/%s' % (path,1)
 
  def kill_process(self,pid):
    """
    殺死程序
    pass: 一般需要許可權不推薦使用
    :return:
    """
    return self.shell('kill %s' % pid).read().strip()
 
  def quit_app(self,package):
    """
    退出應用
    :return:
    """
    return self.shell('am force-stop %s' % package).read().strip()
 
  def reboot(self):
    """
    重啟裝置
    :return:
    """
    self.adb('reboot')
 
  def recovery(self):
    """
    重啟裝置並進入recovery模式
    :return:
    """
    self.adb('reboot recovery')
 
  def fastboot(self):
    """
    重啟裝置並進入fastboot模式
    :return:
    """
    self.adb('reboot bootloader')
 
  def root(self):
    """
    獲取root狀態
    :return:
    """
    return 'not found' not in self.shell('su -c ls -l /data/').read().strip()
 
  def wifi(self,power):
    """
    開啟/關閉wifi
    pass: 需要root許可權
    :return:
    """
    if not self.root():
      print('The device not root.')
      return
    if power:
      self.shell('su -c svc wifi enable').read().strip()
    else:
      self.shell('su -c svc wifi disable').read().strip()
 
  def data(self,power):
    """
    開啟/關閉蜂窩資料
    pass: 需要root許可權
    :return:
    """
    if not self.root():
      print('The device not root.')
      return
    if power:
      self.shell('su -c svc data enable').read().strip()
    else:
      self.shell('su -c svc data disable').read().strip()
 
  def get_wifi_state(self):
    """
    獲取WiFi連線狀態
    :return:
    """
    return 'enabled' in self.shell('dumpsys wifi | %s ^Wi-Fi' % self.__find).read().strip()
 
  def get_data_state(self):
    """
    獲取行動網路連線狀態
    :return:
    """
    return '2' in self.shell('dumpsys telephony.registry | %s mDataConnectionState' % self.__find).read().strip()
 
  def get_network_state(self):
    """
    裝置是否連上網際網路
    :return:
    """
    return 'unknown host' not in self.shell('ping -w 1 www.baidu.com').read().strip()
 
  def get_wifi_password_list(self):
    """
    獲取WIFI密碼列表
    :return:
    """
    if not self.root():
      print('The device not root.')
      return []
    l = re.findall(re.compile('ssid=".+?"\s{3}psk=".+?"'),self.shell('su -c cat /data/misc/wifi/*.conf').read())
    return [re.findall(re.compile('".+?"'),i) for i in l]
 
  def call(self,number):
    """
    撥打電話
    :param number:
    :return:
    """
    self.shell('am start -a android.intent.action.CALL -d tel:%s' % number)
 
  def open_url(self,url):
    """
    開啟網頁
    :return:
    """
    self.shell('am start -a android.intent.action.VIEW -d %s' % url)
 
  def start_application(self,component):
    """
    啟動一個應用
    e.g: com.android.settings/com.android.settings.Settings
    """
    self.shell("am start -n %s" % component)
 
  def send_keyevent(self,keycode):
    """
    傳送一個按鍵事件
    https://developer.android.com/reference/android/view/KeyEvent.html
    :return:
    """
    self.shell('input keyevent %s' % keycode)
 
  def rotation_screen(self,param):
    """
    旋轉螢幕
    :param param: 0 >> 縱向,禁止自動旋轉; 1 >> 自動旋轉
    :return:
    """
    self.shell('/system/bin/content insert --uri content://settings/system --bind '
          'name:s:accelerometer_rotation --bind value:i:%s' % param)
 
  def instrument(self,command):
    """
    啟動instrument app
    :param command: 命令
    :return:
    """
    return self.shell('am instrument %s' % command).read()
 
  def export_apk(self,package,target_path='',timeout=5000):
    """
    從裝置匯出應用
    :param timeout: 超時時間
    :param target_path: 匯出後apk儲存路徑
    :param package: 包名
    :return:
    """
    num = 0
    if target_path == '':
      self.adb('pull /data/app/%s-1/base.apk %s' % (package,os.path.expanduser('~')))
      while 1:
        num += 1
        if num <= timeout:
          if os.path.exists(os.path.join(os.path.expanduser('~'),'base.apk')):
            os.rename(os.path.join(os.path.expanduser('~'),'base.apk'),os.path.join(os.path.expanduser('~'),'%s.apk' % package))
 
    else:
      self.adb('pull /data/app/%s-1/base.apk %s' % (package,target_path))
      while 1:
        num += 1
        if num <= timeout:
          if os.path.exists(os.path.join(os.path.expanduser('~'),'%s.apk' % package))
 
 
class KeyCode:
  KEYCODE_CALL = 5 # 撥號鍵
  KEYCODE_ENDCALL = 6 # 掛機鍵
  KEYCODE_HOME = 3 # Home鍵
  KEYCODE_MENU = 82 # 選單鍵
  KEYCODE_BACK = 4 # 返回鍵
  KEYCODE_SEARCH = 84 # 搜尋鍵
  KEYCODE_CAMERA = 27 # 拍照鍵
  KEYCODE_FOCUS = 80 # 對焦鍵
  KEYCODE_POWER = 26 # 電源鍵
  KEYCODE_NOTIFICATION = 83 # 通知鍵
  KEYCODE_MUTE = 91 # 話筒靜音鍵
  KEYCODE_VOLUME_MUTE = 164 # 揚聲器靜音鍵
  KEYCODE_VOLUME_UP = 24 # 音量+鍵
  KEYCODE_VOLUME_DOWN = 25 # 音量-鍵
  KEYCODE_ENTER = 66 # 回車鍵
  KEYCODE_ESCAPE = 111 # ESC鍵
  KEYCODE_DPAD_CENTER = 23 # 導航鍵 >> 確定鍵
  KEYCODE_DPAD_UP = 19 # 導航鍵 >> 向上
  KEYCODE_DPAD_DOWN = 20 # 導航鍵 >> 向下
  KEYCODE_DPAD_LEFT = 21 # 導航鍵 >> 向左
  KEYCODE_DPAD_RIGHT = 22 # 導航鍵 >> 向右
  KEYCODE_MOVE_HOME = 122 # 游標移動到開始鍵
  KEYCODE_MOVE_END = 123 # 游標移動到末尾鍵
  KEYCODE_PAGE_UP = 92 # 向上翻頁鍵
  KEYCODE_PAGE_DOWN = 93 # 向下翻頁鍵
  KEYCODE_DEL = 67 # 退格鍵
  KEYCODE_FORWARD_DEL = 112 # 刪除鍵
  KEYCODE_INSERT = 124 # 插入鍵
  KEYCODE_TAB = 61 # Tab鍵
  KEYCODE_NUM_LOCK = 143 # 小鍵盤鎖
  KEYCODE_CAPS_LOCK = 115 # 大寫鎖定鍵
  KEYCODE_BREAK = 121 # Break / Pause鍵
  KEYCODE_SCROLL_LOCK = 116 # 滾動鎖定鍵
  KEYCODE_ZOOM_IN = 168 # 放大鍵
  KEYCODE_ZOOM_OUT = 169 # 縮小鍵
  KEYCODE_0 = 7
  KEYCODE_1 = 8
  KEYCODE_2 = 9
  KEYCODE_3 = 10
  KEYCODE_4 = 11
  KEYCODE_5 = 12
  KEYCODE_6 = 13
  KEYCODE_7 = 14
  KEYCODE_8 = 15
  KEYCODE_9 = 16
  KEYCODE_A = 29
  KEYCODE_B = 30
  KEYCODE_C = 31
  KEYCODE_D = 32
  KEYCODE_E = 33
  KEYCODE_F = 34
  KEYCODE_G = 35
  KEYCODE_H = 36
  KEYCODE_I = 37
  KEYCODE_J = 38
  KEYCODE_K = 39
  KEYCODE_L = 40
  KEYCODE_M = 41
  KEYCODE_N = 42
  KEYCODE_O = 43
  KEYCODE_P = 44
  KEYCODE_Q = 45
  KEYCODE_R = 46
  KEYCODE_S = 47
  KEYCODE_T = 48
  KEYCODE_U = 49
  KEYCODE_V = 50
  KEYCODE_W = 51
  KEYCODE_X = 52
  KEYCODE_Y = 53
  KEYCODE_Z = 54
  KEYCODE_PLUS = 81 # +
  KEYCODE_MINUS = 69 # -
  KEYCODE_STAR = 17 # *
  KEYCODE_SLASH = 76 # /
  KEYCODE_EQUALS = 70 # =
  KEYCODE_AT = 77 # @
  KEYCODE_POUND = 18 # #
  KEYCODE_APOSTROPHE = 75 # '
  KEYCODE_BACKSLASH = 73 # \
  KEYCODE_COMMA = 55 #,KEYCODE_PERIOD = 56 # .
  KEYCODE_LEFT_BRACKET = 71 # [
  KEYCODE_RIGHT_BRACKET = 72 # ]
  KEYCODE_SEMICOLON = 74 # ;
  KEYCODE_GRAVE = 68 # `
  KEYCODE_SPACE = 62 # 空格鍵
  KEYCODE_MEDIA_PLAY = 126 # 多媒體鍵 >> 播放
  KEYCODE_MEDIA_STOP = 86 # 多媒體鍵 >> 停止
  KEYCODE_MEDIA_PAUSE = 127 # 多媒體鍵 >> 暫停
  KEYCODE_MEDIA_PLAY_PAUSE = 85 # 多媒體鍵 >> 播放 / 暫停
  KEYCODE_MEDIA_FAST_FORWARD = 90 # 多媒體鍵 >> 快進
  KEYCODE_MEDIA_REWIND = 89 # 多媒體鍵 >> 快退
  KEYCODE_MEDIA_NEXT = 87 # 多媒體鍵 >> 下一首
  KEYCODE_MEDIA_PREVIOUS = 88 # 多媒體鍵 >> 上一首
  KEYCODE_MEDIA_CLOSE = 128 # 多媒體鍵 >> 關閉
  KEYCODE_MEDIA_EJECT = 129 # 多媒體鍵 >> 彈出
  KEYCODE_MEDIA_RECORD = 130 # 多媒體鍵 >> 錄音
 
 
if __name__ == '__main__':
  a = AdbTools()
  pass

補充知識:Python呼叫adb命令實現對多臺裝置同時進行reboot

首先,adb實現對裝置的reboot命令是:adb reboot . 但是如果是兩臺/多臺裝置的時候,需要宣告serial number: adb -s serial_no reboot.

那麼,如何用python實現對多臺裝置進行adb操作呢(reboot)?

這裡涉及到 python 下 subprocess model的使用:

import subprocess

adb device 獲取所有裝置的 serial number:

devices = subprocess.Popen(
  'adb devices'.split(),stdout=subprocess.PIPE,stderr=subprocess.PIPE
).communicate()[0]

這樣adb device命令的返回資訊都在devices下,但是我們只需要 serial number的:

serial_nos = []
for item in devices.split():
  filters = ['list','of','device','devices','attached']
  if item.lower() not in filters:
    serial_nos.append(item)

這樣serial_nos 下儲存的就是所有裝置的 serial number 了,下面我們只需要依次對其進行adb -s [serial_number] reboot即可:

for serial_no in serial_nos:
  reboot_cmds.append('adb -s %s reboot' % serial_no)
for reboot_cmd in reboot_cmds:
  subprocess.Popen(
    reboot_cmd.split(),stderr=subprocess.PIPE
  ).communicate()[0]

這樣,每個裝置都進行了reboot的操作了……

以上這篇Python實現對adb命令封裝就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。