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

Python封裝adb命令的操作詳解

 更新時間:2024年01月18日 08:45:13   作者:麥田里的守望者江  
在日常的 Android 項(xiàng)目開發(fā)中,我們通常會使用 adb 命令來獲取連接設(shè)備的內(nèi)存、屏幕、CPU等信息,這些信息的獲取,每次都在command 中輸入相關(guān)命令進(jìn)行重復(fù)的操作讓人感到厭倦和疲乏,現(xiàn)在,可以嘗試使用 python 來簡化這一部分工作,所以本文介紹了Python封裝adb命令的操作

引言

在日常的 Android 項(xiàng)目開發(fā)中,我們通常會使用 adb 命令來獲取連接設(shè)備的內(nèi)存、屏幕、CPU等信息,也會使用 gradle 命令來獲取項(xiàng)目構(gòu)建相關(guān)的 projects、tasks、dependencies等信息,還會使用 git 命令來獲取代碼 commit、log、diff 等信息。這些信息的獲取,每次都在command 中輸入相關(guān)命令進(jìn)行操作(有時命令記不住,還需要查詢一下),重復(fù)的操作讓人感到厭倦和疲乏?,F(xiàn)在,可以嘗試使用 python 來簡化這一部分工作,將常用的執(zhí)行命令封裝到 python 腳本中,每次想要獲取某個信息時,就直接執(zhí)行相關(guān) python 腳本。這樣就可以省去開發(fā)中的細(xì)碎工作。(將腳本一次寫好,使用到退休:))

python 準(zhǔn)備

使用 Python 腳本封裝常用的 adb、gradle、git 命令,首先需要對 python 有一定的基本了解。

使用 subprocess 模塊

subprocess 模塊是 Python 中執(zhí)行外部命令的標(biāo)準(zhǔn)庫。通過該模塊,可以執(zhí)行 adb、gradle、git 等命令,以及獲取命令輸出結(jié)果。

import subprocess

result = subprocess.run(['adb', 'devices'], capture_output=True, text=True, check=True)
print(result.stdout)

將執(zhí)行命令的操作簡單地封裝成一個方法:

def run_command(command):
    try:
        result = subprocess.run(command, check=True, text=True, capture_output=True)
        return result.stdout
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {e}")
        return None
      
result = run_command(['adb', 'devices'])
print(result)

如果要實(shí)時打印執(zhí)行命令的每一行結(jié)果,可以使用 subprocess.Popen 方法:

def run_command_process(command):
    try:
        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                print("stop")
                break
            if output:
                print(output.strip())

        return process.returncode
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {e}")
        return None

切換工作目錄路徑

使用 os 模塊中的 chdir 函數(shù)可以切換當(dāng)前工作目錄的路徑:

import os

os.chdir(current_project_path)

執(zhí)行 adb 命令

在日常的 Android 項(xiàng)目開發(fā)中,通常使用 adb 命令來獲取屏幕、設(shè)備、應(yīng)用程序等信息。

首先定義一個執(zhí)行 adb 命令的基礎(chǔ)方法:

def run_adb_command(adb_path='adb', command=None):
    """
    :param adb_path: adb 工具路徑,如果在系統(tǒng)環(huán)境中配置了adb路徑,則不需要傳遞,否則需要
    :param command: 實(shí)際相關(guān)命令
    :return: 執(zhí)行命令結(jié)果
    """
    if command is None:
        command = []
    try:
        command.insert(0, adb_path)
        return subprocess.run(command, check=True, text=True, capture_output=True, encoding='utf-8')
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {e}")
        return None

操作組合-截屏

截屏算是 Android 開發(fā)中的一個頻繁操作。在通常情況下,截屏操作步驟為:在設(shè)備上點(diǎn)擊截屏 → 找到設(shè)備上存儲的截屏文件地址 → 使用 adb pull 將截屏文件保存到電腦上 → 在電腦上打開截屏文件(或者使用 Android Studio 的 Logcat 面板截屏)。如果使用 pythoh,那么就可以將這幾個步驟組合,然后寫成一個 pythoh 腳本。

第一步:截屏并保存到設(shè)備

  • 獲取設(shè)備外部存儲根路徑命令:adb shell echo '$EXTERNAL_STORAGE'
  • 截屏命令:adb shell screencap -p screen_cap_file_path,screen_cap_file_path為截屏文件地址,該地址和名稱可以自定義
  • 創(chuàng)建文件目錄:adb shell mkdir -p file_dir,file_dir 為文件目錄
def screen_cap(adb_path='adb'):
    """
    截屏并保存到設(shè)備外部存儲卡 /Pictures/Screenshots 目錄下,截屏文件名為規(guī)則為Screenshot_年月日_時分秒.png,例如:Screenshot_20220502_175425.png
    :param adb_path: adb 工具路徑
    :return: 截屏文件路徑和名稱
    """
    current_time = time.strftime("%Y%m%d_%H%M%S", time.localtime())
    screen_cap_name = 'Screenshot_' + current_time + '.png'
    # 獲取手機(jī)外部存儲目錄
    external_result = run_adb_command(adb_path, ['shell', "'echo'", '$EXTERNAL_STORAGE'])
    external_dir = external_result.stdout.strip()
    android_file_separator = '/'
    screen_cap_file_dir = external_dir + android_file_separator + 'Pictures' + android_file_separator + 'Screenshots'
    # 創(chuàng)建文件夾 adb shell mkdir -p file_dir
    run_adb_command(adb_path, ['shell', 'mkdir', '-p', screen_cap_file_dir])
    screen_cap_file_path = screen_cap_file_dir + android_file_separator + screen_cap_name
    screen_cap_result = run_adb_command(adb_path, ['shell', 'screencap', '-p', screen_cap_file_path])
    if screen_cap_result.returncode == 0:
        return [screen_cap_file_path, screen_cap_name]
    else:
        print(screen_cap_result.stderr)
        return ["", ""]

第二步:保存截屏文件到電腦

  • 保存截屏文件到電腦命令:adb pull src_file_path des_file_path,src_file_path 為截屏文件在設(shè)備上的地址,des_file_path 為截屏文件保存到電腦上的地址。
def pull_screen_cap(src_file_path, des_file_path, adb_path='adb'):
    """
    將截屏文件保存到電腦上
    :param src_file_path: 設(shè)備截屏文件地址
    :param des_file_path: 電腦上文件地址
    :param adb_path: adb 工具路徑
    :return: ture表示成功,否則失敗
    """
    pull_screen_cap_result = run_adb_command(adb_path, ['pull', src_file_path, des_file_path])
    return pull_screen_cap_result.returncode == 0


def get_desktop_path(screen_cap_name):
    """
    獲取保存到電腦上的截屏文件路徑
    :param screen_cap_name: 截屏文件名稱
    :return: 電腦上桌面中的截屏文件路徑
    """
    desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
    return desktop_path + os.path.sep + screen_cap_name

第三步:在電腦上打開截屏文件

  • windows 打開文件命令:start file_path
  • mac 打開文件命令:open file_path
def open_file(file_path):
    """
    在電腦上打開截屏文件
    :param file_path: 電腦上的截屏文件地址
    """
    system = platform.system().lower()
    if system == "darwin":  # macOS
        subprocess.run(["open", file_path])
    elif system == "linux":  # Linux
        subprocess.run(["xdg-open", file_path])
    elif system == "windows":  # Windows
        subprocess.run(["start", file_path], shell=True)
    else:
        print("Unsupported operating system.")

將上面步驟組合在一起:

if __name__ == '__main__':
    screen_cap_file_path, screen_cap_name = screen_cap()
    if len(screen_cap_file_path) > 0:
        des_file_path = get_desktop_path(screen_cap_name)
        result = pull_screen_cap(screen_cap_file_path, des_file_path)
        if result:
            print(f"Screenshot path: {des_file_path}")
            open_file(des_file_path)
        else:
            print("Failed to take a screenshot")

將上面的代碼放到 screencap.py 中,在需要截屏的時候,執(zhí)行 python3 screencap.py 腳本,就可以自動截屏并在電腦上打開截屏文件。

操作簡化-基礎(chǔ)信息

獲取設(shè)備上的三方應(yīng)用程序的 Main Activity(啟動 Activity)信息

如果直接使用 adb 命令,獲取設(shè)備上的三方應(yīng)用程序的 Main Activity(啟動 Activity)信息,是非常繁瑣的。利用 python,可以將操作簡化,而且將信息格式化。

第一步:獲取三方應(yīng)用程序包名

  • 獲取設(shè)備上安裝的三方應(yīng)用程序列表命令:adb shell pm list packages -3 -f
  • 利用正則表達(dá)式找到應(yīng)用程序包名:r"base.apk=(\S+)"
def get_third_party_app_activities(adb_path='adb'):
    """
    獲取設(shè)備上的三方應(yīng)用程序的 main activity
    :param adb_path: adb 工具的路徑
    :return:三方應(yīng)用程序的 main activity 信息
    """
    result = run_adb_command(adb_path, ['shell', 'pm', 'list', 'packages', '-3', '-f'])
    third_party_app_main_activities = []
    if result is not None:
        # 使用正則表達(dá)式提取包名
        package_names = re.findall(r"base.apk=(\S+)", result)
        print(package_names)
        # 獲取每個應(yīng)用程序的主活動
        for package_name in package_names:
            activity = get_main_activity(package_name)
            if activity:
                third_party_app_main_activities.append(f"Package: {package_name}, Main Activity: {activity}")
    return '\n'.join(third_party_app_main_activities)

第二步:通過應(yīng)用程序包名獲取 Main Activity

  • 獲取應(yīng)用程序 Main Activity 命令:adb shell dumpsys package package_name | grep -A 1 MAIN
def get_main_activity(package_name, adb_path='adb'):
    """
    根據(jù)包名獲取 main activity
    :param package_name: 應(yīng)用程序包名
    :param adb_path: adb 工具的路徑
    :return: main activity 信息,例如:com.tencent.mm/.ui.LauncherUI
    """
    try:
        result = run_adb_command(adb_path,
                                  ['shell', 'dumpsys', 'package', package_name, '|', 'grep', '-A', '1', 'MAIN'])
        if result is not None:
            # 使用正則表達(dá)式提取 main activity
            text = result.strip()
            end_flag = 'filter'
            end_index = text.index(end_flag)
            android_file_separator = '/'
            start_flag = package_name + android_file_separator
            start_index = text.index(start_flag, 0, end_index)
            main_activity = text[start_index:end_index]
            if main_activity.startswith(package_name):
                return main_activity
            else:
                print("Error extracting main activity: index-" + package_name)
                return None
        else:
            print("Error extracting main activity: code-" + package_name)
            return None
    except AttributeError:
        print("Error extracting main activity: caught-" + package_name)

執(zhí)行上面代碼可以看到:

if __name__ == "__main__":
    print(get_third_party_app_activities())

輸出結(jié)果:
Package: com.tencent.mm, Main Activity: com.tencent.mm/.ui.LauncherUI 
Package: com.sangfor.vpn.client.phone, Main Activity: com.sangfor.vpn.client.phone/.WelcomeActivity 
Package: com.huawei.cloud, Main Activity: com.huawei.cloud/.wi.WIActivity 
Package: com.meishe.myvideoapp, Main Activity: com.meishe.myvideoapp/com.meishe.myvideo.activity.MainActivity 
Package: com.screeclibinvoke, Main Activity: com.screeclibinvoke/.component.activity.AppStartActivity 
Package: com.tencent.wework, Main Activity: com.tencent.wework/.launch.LaunchSplashActivity 

獲取設(shè)備上當(dāng)前應(yīng)用程序的當(dāng)前Activity

獲取設(shè)備上當(dāng)前應(yīng)用程序的當(dāng)前Activity,對于快速定位代碼是非常有幫助的。利用 python 可以輕松搞定:

def get_top_activity(adb_path='adb'):
    return _run_adb_command(adb_path,
                            ['shell', 'dumpsys', 'activity', 'top', '|', 'grep', 'ACTIVITY', '|', 'tail', '-n', '1'])

執(zhí)行結(jié)果:

ACTIVITY com.tencent.wework/.login.controller.LoginWxAuthActivity 8e93087 pid=22406

小結(jié)

上面簡單介紹了使用 python 執(zhí)行 adb 命令獲取截屏、三方應(yīng)用程序Main Activity、當(dāng)前應(yīng)用程序當(dāng)前Activity信息,可以看到在 python 中,將相關(guān) adb 命令操作組合或簡化后輸出,能夠快速的得到關(guān)鍵信息,這就可以省去了部分瑣碎時間。其它信息的獲取,例如:

  • 獲取設(shè)備基礎(chǔ)信息:adb shell getprop
  • 獲取設(shè)備屏幕信息:adb shell wm size 或 adb shell wm density
  • 獲取設(shè)備cpu信息:adb shell cat /proc/cpuinfo
  • 獲取設(shè)備memory信息:adb shell cat /proc/meminfo
  • 其它

也可以使用 python,這里就不再將每一個列舉。

以上就是Python封裝adb命令的操作詳解的詳細(xì)內(nèi)容,更多關(guān)于Python封裝adb命令的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論