欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python實(shí)現(xiàn)對(duì)adb命令封裝

 更新時(shí)間:2020年03月06日 18:39:48   作者:柒肆·  
這篇文章主要介紹了Python實(shí)現(xiàn)對(duì)adb命令封裝,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

我就廢話不多說(shuō)了,大家還是直接看代碼吧!

#!/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):
    """
    判斷系統(tǒng)類型,windows使用findstr,linux使用grep
    :return:
    """
    if self.__system is "Windows":
      self.__find = "findstr"
    else:
      self.__find = "grep"
 
  def __check_adb(self):
    """
    檢查adb
    判斷是否設(shè)置環(huán)境變量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"], "platform-tools", "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):
    """
    連接指定設(shè)備,單個(gè)設(shè)備可不傳device_id
    :return:
    """
    if self.__device_id == "":
      return
    self.__device_id = "-s %s" % self.__device_id
 
  def adb(self, args):
    """
    執(zhí)行adb命令
    :param args:參數(shù)
    :return:
    """
    cmd = "%s %s %s" % (self.__command, self.__device_id, str(args))
    # print(cmd)
    return os.popen(cmd)
 
  def shell(self, args):
    """
    執(zhí)行adb shell命令
    :param args:參數(shù)
    :return:
    """
    cmd = "%s %s shell %s" % (self.__command, self.__device_id, str(args))
    # print(cmd)
    return os.popen(cmd)
 
  def mkdir(self, path):
    """
    創(chuàng)建目錄
    :param path: 路徑
    :return:
    """
    return self.shell('mkdir %s' % path)
 
  def get_devices(self):
    """
    獲取設(shè)備列表
    :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):
    """
    獲取當(dāng)前運(yùn)行的應(yīng)用信息
    :return:
    """
    return self.shell('dumpsys window w | %s \/ | %s name=' % (self.__find, self.__find)).read()
 
  def get_current_package(self):
    """
    獲取當(dāng)前運(yùn)行app包名
    :return:
    """
    reg = re.compile(r'name=(.+?)/')
    return re.findall(reg, self.get_current_application())[0]
 
  def get_current_activity(self):
    """
    獲取當(dāng)前運(yùn)行activity
    :return: package/activity
    """
    reg = re.compile(r'name=(.+?)\)')
    return re.findall(reg, self.get_current_application())[0]
 
  def __get_process(self, package_name):
    """
    獲取進(jìn)程信息
    :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):
    """
    返回進(jìn)程是否存在
    :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):
    """
    獲取應(yīng)用tcp流量
    :return:(接收, 發(fā)送)
    """
    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):
    """
    獲取應(yīng)用流量全部數(shù)據(jù)
    包含該應(yīng)用多個(gè)進(jìn)程的所有數(shù)據(jù) tcp udp等
    (rx_bytes, tx_bytes) >> (接收, 發(fā)送)
    :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是否添加到環(huán)境變量中
    # 需要用到里面的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):
    """
    從手機(jī)端拉取文件到電腦端
    :return:
    """
    self.adb('pull %s %s' % (source, target))
 
  def push(self, source, target):
    """
    從電腦端推送文件到手機(jī)端
    :param source:
    :param target:
    :return:
    """
    self.adb('push %s %s' % (source, target))
 
  def remove(self, path):
    """
    從手機(jī)端刪除文件
    :return:
    """
    self.shell('rm %s' % (path,))
 
  def clear_app_data(self, package):
    """
    清理應(yīng)用數(shù)據(jù)
    :return:
    """
    self.shell('pm clear %s' % (package,))
 
  def install(self, path):
    """
    安裝apk文件
    :return:
    """
    # adb install 安裝錯(cuò)誤常見(jiàn)列表
    errors = {'INSTALL_FAILED_ALREADY_EXISTS': '程序已經(jīng)存在',
         'INSTALL_DEVICES_NOT_FOUND': '找不到設(shè)備',
         'INSTALL_FAILED_DEVICE_OFFLINE': '設(shè)備離線',
         'INSTALL_FAILED_INVALID_APK': '無(wú)效的APK',
         'INSTALL_FAILED_INVALID_URI': '無(wú)效的鏈接',
         'INSTALL_FAILED_INSUFFICIENT_STORAGE': '沒(méi)有足夠的存儲(chǔ)空間',
         'INSTALL_FAILED_DUPLICATE_PACKAGE': '已存在同名程序',
         'INSTALL_FAILED_NO_SHARED_USER': '要求的共享用戶不存在',
         'INSTALL_FAILED_UPDATE_INCOMPATIBLE': '版本不能共存',
         'INSTALL_FAILED_SHARED_USER_INCOMPATIBLE': '需求的共享用戶簽名錯(cuò)誤',
         'INSTALL_FAILED_MISSING_SHARED_LIBRARY': '需求的共享庫(kù)已丟失',
         'INSTALL_FAILED_REPLACE_COULDNT_DELETE': '需求的共享庫(kù)無(wú)效',
         'INSTALL_FAILED_DEXOPT': 'dex優(yōu)化驗(yàn)證失敗',
         'INSTALL_FAILED_DEVICE_NOSPACE': '手機(jī)存儲(chǔ)空間不足導(dǎo)致apk拷貝失敗',
         'INSTALL_FAILED_DEVICE_COPY_FAILED': '文件拷貝失敗',
         'INSTALL_FAILED_OLDER_SDK': '系統(tǒng)版本過(guò)舊',
         'INSTALL_FAILED_CONFLICTING_PROVIDER': '存在同名的內(nèi)容提供者',
         'INSTALL_FAILED_NEWER_SDK': '系統(tǒng)版本過(guò)新',
         'INSTALL_FAILED_TEST_ONLY': '調(diào)用者不被允許測(cè)試的測(cè)試程序',
         'INSTALL_FAILED_CPU_ABI_INCOMPATIBLE': '包含的本機(jī)代碼不兼容',
         'CPU_ABIINSTALL_FAILED_MISSING_FEATURE': '使用了一個(gè)無(wú)效的特性',
         'INSTALL_FAILED_CONTAINER_ERROR': 'SD卡訪問(wèn)失敗',
         'INSTALL_FAILED_INVALID_INSTALL_LOCATION': '無(wú)效的安裝路徑',
         'INSTALL_FAILED_MEDIA_UNAVAILABLE': 'SD卡不存在',
         'INSTALL_FAILED_INTERNAL_ERROR': '系統(tǒng)問(wèn)題導(dǎo)致安裝失敗',
         'INSTALL_PARSE_FAILED_NO_CERTIFICATES': '文件未通過(guò)認(rèn)證 >> 設(shè)置開(kāi)啟未知來(lái)源',
         'INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES': '文件認(rèn)證不一致 >> 先卸載原來(lái)的再安裝',
         'INSTALL_FAILED_INVALID_ZIP_FILE': '非法的zip文件 >> 先卸載原來(lái)的再安裝',
         'INSTALL_CANCELED_BY_USER': '需要用戶確認(rèn)才可進(jìn)行安裝',
         'INSTALL_FAILED_VERIFICATION_FAILURE': '驗(yàn)證失敗 >> 嘗試重啟手機(jī)',
         'DEFAULT': '未知錯(cuò)誤'
         }
    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=''):
    """
    手機(jī)截圖
    :param target_path: 目標(biāo)路徑
    :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):
    """
    導(dǎo)出緩存日志
    :return:
    """
    return self.adb('logcat -v time -d')
 
  def get_crash_logcat(self):
    """
    導(dǎo)出崩潰日志
    :return:
    """
    return self.adb('logcat -v time -d | %s AndroidRuntime' % (self.__find,))
 
  def clear_cache_logcat(self):
    """
    清理緩存區(qū)日志
    :return:
    """
    self.adb('logcat -c')
 
  def get_device_time(self):
    """
    獲取設(shè)備時(shí)間
    :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):
    """
    判斷文件在目標(biāo)路徑是否存在
    :return:
    """
    l = self.ls(target)
    for i in l:
      if i.strip() == target:
        return True
    return False
 
  def is_install(self, target_app):
    """
    判斷目標(biāo)app在設(shè)備上是否已安裝
    :param target_app: 目標(biāo)app包名
    :return: bool
    """
    return target_app in self.shell('pm list packages %s' % (target_app,)).read()
 
  def get_device_model(self):
    """
    獲取設(shè)備型號(hào)
    :return:
    """
    return self.shell('getprop ro.product.model').read().strip()
 
  def get_device_id(self):
    """
    獲取設(shè)備id
    :return:
    """
    return self.adb('get-serialno').read().strip()
 
  def get_device_android_version(self):
    """
    獲取設(shè)備Android版本
    :return:
    """
    return self.shell('getprop ro.build.version.release').read().strip()
 
  def get_device_sdk_version(self):
    """
    獲取設(shè)備SDK版本
    :return:
    """
    return self.shell('getprop ro.build.version.sdk').read().strip()
 
  def get_device_mac_address(self):
    """
    獲取設(shè)備MAC地址
    :return:
    """
    return self.shell('cat /sys/class/net/wlan0/address').read().strip()
 
  def get_device_ip_address(self):
    """
    獲取設(shè)備IP地址
    pass: 適用WIFI 蜂窩數(shù)據(jù)
    :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):
    """
    獲取設(shè)備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):
    """
    檢查設(shè)備SIM卡
    :return:
    """
    return len(self.shell('getprop | %s gsm.operator.alpha]' % self.__find).read().strip().split()[-1]) > 2
 
  def get_device_operators(self):
    """
    獲取運(yùn)營(yíng)商
    :return:
    """
    return self.shell('getprop | %s gsm.operator.alpha]' % self.__find).read().strip().split()[-1]
 
  def get_device_state(self):
    """
    獲取設(shè)備狀態(tài)
    :return:
    """
    return self.adb('get-state').read().strip()
 
  def get_display_state(self):
    """
    獲取屏幕狀態(tài)
    :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):
    """
    獲取設(shè)備屏幕分辨率 >> 標(biāo)配
    :return:
    """
    return self.shell('wm size').read().strip().split()[-1].split('x')
 
  def get_screen_reality_size(self):
    """
    獲取設(shè)備屏幕分辨率 >> 實(shí)際分辨率
    :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):
    """
    獲取內(nèi)部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,total,used,free,block)
    """
    return self.shell('df | %s \/storage' % self.__find).read().strip().split()
 
  def __fill_rom(self, path, stream, count):
    """
    填充數(shù)據(jù)
    :param path: 填充地址
    :param stream: 填充流大小
    :param count: 填充次數(shù)
    :return:
    """
    self.shell('dd if=/dev/zero of=%s bs=%s count=%s' % (path, stream, count)).read().strip()
 
  def fill_interior_sdcard(self, filename, size):
    """
    填充內(nèi)置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, filename, 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), 10485760, size / 10485760)
    else:
      self.__fill_rom('%s/%s' % (path, filename), size, 1)
 
  def kill_process(self, pid):
    """
    殺死進(jìn)程
    pass: 一般需要權(quán)限不推薦使用
    :return:
    """
    return self.shell('kill %s' % pid).read().strip()
 
  def quit_app(self, package):
    """
    退出應(yīng)用
    :return:
    """
    return self.shell('am force-stop %s' % package).read().strip()
 
  def reboot(self):
    """
    重啟設(shè)備
    :return:
    """
    self.adb('reboot')
 
  def recovery(self):
    """
    重啟設(shè)備并進(jìn)入recovery模式
    :return:
    """
    self.adb('reboot recovery')
 
  def fastboot(self):
    """
    重啟設(shè)備并進(jìn)入fastboot模式
    :return:
    """
    self.adb('reboot bootloader')
 
  def root(self):
    """
    獲取root狀態(tài)
    :return:
    """
    return 'not found' not in self.shell('su -c ls -l /data/').read().strip()
 
  def wifi(self, power):
    """
    開(kāi)啟/關(guān)閉wifi
    pass: 需要root權(quán)限
    :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):
    """
    開(kāi)啟/關(guān)閉蜂窩數(shù)據(jù)
    pass: 需要root權(quán)限
    :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連接狀態(tài)
    :return:
    """
    return 'enabled' in self.shell('dumpsys wifi | %s ^Wi-Fi' % self.__find).read().strip()
 
  def get_data_state(self):
    """
    獲取移動(dòng)網(wǎng)絡(luò)連接狀態(tài)
    :return:
    """
    return '2' in self.shell('dumpsys telephony.registry | %s mDataConnectionState' % self.__find).read().strip()
 
  def get_network_state(self):
    """
    設(shè)備是否連上互聯(lián)網(wǎng)
    :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):
    """
    打開(kāi)網(wǎng)頁(yè)
    :return:
    """
    self.shell('am start -a android.intent.action.VIEW -d %s' % url)
 
  def start_application(self, component):
    """
    啟動(dòng)一個(gè)應(yīng)用
    e.g: com.android.settings/com.android.settings.Settings
    """
    self.shell("am start -n %s" % component)
 
  def send_keyevent(self, keycode):
    """
    發(fā)送一個(gè)按鍵事件
    https://developer.android.com/reference/android/view/KeyEvent.html
    :return:
    """
    self.shell('input keyevent %s' % keycode)
 
  def rotation_screen(self, param):
    """
    旋轉(zhuǎn)屏幕
    :param param: 0 >> 縱向,禁止自動(dòng)旋轉(zhuǎn); 1 >> 自動(dòng)旋轉(zhuǎn)
    :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):
    """
    啟動(dòng)instrument app
    :param command: 命令
    :return:
    """
    return self.shell('am instrument %s' % command).read()
 
  def export_apk(self, package, target_path='', timeout=5000):
    """
    從設(shè)備導(dǎo)出應(yīng)用
    :param timeout: 超時(shí)時(shí)間
    :param target_path: 導(dǎo)出后apk存儲(chǔ)路徑
    :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('~'), 'base.apk')):
            os.rename(os.path.join(os.path.expanduser('~'), 'base.apk'),
                 os.path.join(os.path.expanduser('~'), '%s.apk' % package))
 
 
class KeyCode:
  KEYCODE_CALL = 5 # 撥號(hào)鍵
  KEYCODE_ENDCALL = 6 # 掛機(jī)鍵
  KEYCODE_HOME = 3 # Home鍵
  KEYCODE_MENU = 82 # 菜單鍵
  KEYCODE_BACK = 4 # 返回鍵
  KEYCODE_SEARCH = 84 # 搜索鍵
  KEYCODE_CAMERA = 27 # 拍照鍵
  KEYCODE_FOCUS = 80 # 對(duì)焦鍵
  KEYCODE_POWER = 26 # 電源鍵
  KEYCODE_NOTIFICATION = 83 # 通知鍵
  KEYCODE_MUTE = 91 # 話筒靜音鍵
  KEYCODE_VOLUME_MUTE = 164 # 揚(yáng)聲器靜音鍵
  KEYCODE_VOLUME_UP = 24 # 音量+鍵
  KEYCODE_VOLUME_DOWN = 25 # 音量-鍵
  KEYCODE_ENTER = 66 # 回車(chē)鍵
  KEYCODE_ESCAPE = 111 # ESC鍵
  KEYCODE_DPAD_CENTER = 23 # 導(dǎo)航鍵 >> 確定鍵
  KEYCODE_DPAD_UP = 19 # 導(dǎo)航鍵 >> 向上
  KEYCODE_DPAD_DOWN = 20 # 導(dǎo)航鍵 >> 向下
  KEYCODE_DPAD_LEFT = 21 # 導(dǎo)航鍵 >> 向左
  KEYCODE_DPAD_RIGHT = 22 # 導(dǎo)航鍵 >> 向右
  KEYCODE_MOVE_HOME = 122 # 光標(biāo)移動(dòng)到開(kāi)始鍵
  KEYCODE_MOVE_END = 123 # 光標(biāo)移動(dòng)到末尾鍵
  KEYCODE_PAGE_UP = 92 # 向上翻頁(yè)鍵
  KEYCODE_PAGE_DOWN = 93 # 向下翻頁(yè)鍵
  KEYCODE_DEL = 67 # 退格鍵
  KEYCODE_FORWARD_DEL = 112 # 刪除鍵
  KEYCODE_INSERT = 124 # 插入鍵
  KEYCODE_TAB = 61 # Tab鍵
  KEYCODE_NUM_LOCK = 143 # 小鍵盤(pán)鎖
  KEYCODE_CAPS_LOCK = 115 # 大寫(xiě)鎖定鍵
  KEYCODE_BREAK = 121 # Break / Pause鍵
  KEYCODE_SCROLL_LOCK = 116 # 滾動(dòng)鎖定鍵
  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 # 多媒體鍵 >> 快進(jìn)
  KEYCODE_MEDIA_REWIND = 89 # 多媒體鍵 >> 快退
  KEYCODE_MEDIA_NEXT = 87 # 多媒體鍵 >> 下一首
  KEYCODE_MEDIA_PREVIOUS = 88 # 多媒體鍵 >> 上一首
  KEYCODE_MEDIA_CLOSE = 128 # 多媒體鍵 >> 關(guān)閉
  KEYCODE_MEDIA_EJECT = 129 # 多媒體鍵 >> 彈出
  KEYCODE_MEDIA_RECORD = 130 # 多媒體鍵 >> 錄音
 
 
if __name__ == '__main__':
  a = AdbTools()
  pass

補(bǔ)充知識(shí):Python調(diào)用adb命令實(shí)現(xiàn)對(duì)多臺(tái)設(shè)備同時(shí)進(jìn)行reboot

首先,adb實(shí)現(xiàn)對(duì)設(shè)備的reboot命令是:adb reboot . 但是如果是兩臺(tái)/多臺(tái)設(shè)備的時(shí)候,需要聲明serial number: adb -s serial_no reboot.

那么,如何用python實(shí)現(xiàn)對(duì)多臺(tái)設(shè)備進(jìn)行adb操作呢(reboot)?

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

import subprocess

adb device 獲取所有設(shè)備的 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 下保存的就是所有設(shè)備的 serial number 了,下面我們只需要依次對(duì)其進(jìn)行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(),
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
  ).communicate()[0]

這樣,每個(gè)設(shè)備都進(jìn)行了reboot的操作了……

以上這篇Python實(shí)現(xiàn)對(duì)adb命令封裝就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • openCV中值濾波和均值濾波的代碼實(shí)現(xiàn)

    openCV中值濾波和均值濾波的代碼實(shí)現(xiàn)

    在我們生活中的有很多時(shí)候都可以用到濾波,例如美顏的磨皮功能,本文就詳細(xì)的介紹了openCV中值濾波和均值濾波的代碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Python的time模塊中的常用方法整理

    Python的time模塊中的常用方法整理

    這篇文章主要介紹了Python的time模塊中的常用方法整理,time模塊是專門(mén)用于處理日期時(shí)間的模塊,需要的朋友可以參考下
    2015-06-06
  • Flask框架運(yùn)用Ajax實(shí)現(xiàn)數(shù)據(jù)交互的示例代碼

    Flask框架運(yùn)用Ajax實(shí)現(xiàn)數(shù)據(jù)交互的示例代碼

    使用Ajax技術(shù)網(wǎng)頁(yè)應(yīng)用能夠快速地將增量更新呈現(xiàn)在用戶界面上,而不需要重載刷新整個(gè)頁(yè)面,這使得程序能夠更快地回應(yīng)用戶的操作,本文將簡(jiǎn)單介紹使用AJAX如何實(shí)現(xiàn)前后端數(shù)據(jù)通信
    2022-11-11
  • Python基礎(chǔ)之pandas數(shù)據(jù)合并

    Python基礎(chǔ)之pandas數(shù)據(jù)合并

    這篇文章主要介紹了Python基礎(chǔ)之pandas數(shù)據(jù)合并,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • numpy中數(shù)組的堆疊方法

    numpy中數(shù)組的堆疊方法

    本文主要介紹了numpy中數(shù)組的堆疊方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 對(duì)python dataframe邏輯取值的方法詳解

    對(duì)python dataframe邏輯取值的方法詳解

    今天小編就為大家分享一篇對(duì)python dataframe邏輯取值的方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • Python 音頻生成器的實(shí)現(xiàn)示例

    Python 音頻生成器的實(shí)現(xiàn)示例

    這篇文章主要介紹了Python 音頻生成器的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Python與C語(yǔ)言分別完成排序流程

    Python與C語(yǔ)言分別完成排序流程

    這篇文章主要介紹了Python與C語(yǔ)言分別完成排序的實(shí)例,在Python與C語(yǔ)言基本類型的排序中特別有用,下面我們一起進(jìn)入文章學(xué)習(xí)更詳細(xì)的內(nèi)容吧,需要的朋友可以參考下
    2022-03-03
  • Python Sqlite3以字典形式返回查詢結(jié)果的實(shí)現(xiàn)方法

    Python Sqlite3以字典形式返回查詢結(jié)果的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇Python Sqlite3以字典形式返回查詢結(jié)果的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • django+echart繪制曲線圖的方法示例

    django+echart繪制曲線圖的方法示例

    這篇文章主要介紹了django+echart繪制曲線圖的方法示例,可以了解Django中aggregate和annotate函數(shù)的使用方法及其Django+Echarts繪制柱狀圖的完整示例,感興趣的小伙伴們可以參考一下
    2018-11-11

最新評(píng)論