Skip to main content

A collection of useful adb commands

Project description

A collection of useful adb commands

pip install usefuladb

# Tested against Android 9 / Bluestacks / Python 11 / Windows 10
# Please be aware that Android commands and
# their behavior can vary across different Android
# versions, custom ROMs, and devices. Consequently,
# some commands or methods may not function as
# expected on specific devices or Android versions.
# Moreover, certain advanced operations may
# necessitate root access, which is not universally
# available.
#
# It is advisable to thoroughly test and customize
# your commands and methods according to the
# unique specifications of your device and the
# Android version it runs. Keep in mind that
# Android is a dynamic platform, and commands and
# behaviors may change over time.
# Additionally, when executing commands,
# particularly those requiring elevated privileges,
# it's essential to consider the security
# and permission model of the Android device
from time import sleep

from usefuladb import AdbControl

# To connect to all devices at once, you can use this static method (Windows only):
AdbControl.connect_to_all_tcp_devices_windows(
    adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
)
# Blocking Shell
# - Waits until stderr/stdout have finished processing.
# - if you run "cd /sdcard/" and then another command "ls", for example, you will see the contents of /sdcard/.
# - If you switch to su, you will remain in the superuser mode.
# - Commands are not base64 encoded
addr = "127.0.0.1:5675"

blocking_shell = AdbControl(
    adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
    device_serial=addr,
    use_busybox=False,  # uses busybox to decode base64
    connect_to_device=True,
    invisible=True,  # windows only - doesn't open a shell window, when you compile the code with nuitka, for example
    print_stdout=True,
    print_stderr=True,
    limit_stdout=3,  # limits the history of shellcommands - can be checked at blocking_shell.stdout
    limit_stderr=3,  # limits the history of shellcommands - can be checked at blocking_shell.stderr
    limit_stdin=None,  # limits the history of shellcommands - can be checked at blocking_shell.stdin
    convert_to_83=True,  # converts the adb path to 8.3 on Windows
    wait_to_complete=0,  # doesn't matter if global_cmd is True
    flush_stdout_before=True,  # flushes the history in  blocking_shell.stdout
    flush_stdin_before=True,  # flushes the history in blocking_shell.stderr
    flush_stderr_before=True,  # flushes the history in  blocking_shell.stdin
    exitcommand="xxxCOMMANDxxxDONExxx",
    # Written using echo at the end of every command to determine when the output is finished.
    capture_stdout_stderr_first=True,  # doesn't matter if global_cmd is True
    global_cmd=True,  # global, because variables/su status/dirs stay
    global_cmd_timeout=10,  # if a command doesn't return stderr/stdout in a given time
)

# Blocking Subshell
# - Waits until stderr/stdout have finished processing.
# - Commands are base64 encoded.
# - All commands are executed within a subshell using a pipeline like base64command | base64 -d | sh.
# - For example, if you run "cd /sdcard/" and then another command like "ls," you will see the contents of the root directory '/' instead of '/sdcard'.
# - Note that 'su' is only valid for a single command.
blocking_subshell = AdbControl(
    adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
    device_serial=addr,
    use_busybox=False,  # Use busybox to decode base64 (if needed)
    connect_to_device=True,
    invisible=True,
    # Windows only - This option prevents the shell window from opening, e.g., when compiling the code with Nuitka.
    print_stdout=True,
    print_stderr=True,
    limit_stdout=3,  # Limit the history of shell commands (can be checked at blocking_shell.stdout)
    limit_stderr=3,  # Limit the history of shell commands (can be checked at blocking_shell.stderr)
    limit_stdin=None,  # Limit the history of shell commands (can be checked at blocking_shell.stdin)
    convert_to_83=True,  # Converts the adb path to 8.3 format on Windows
    wait_to_complete=0.1,  # Time to wait for command completion - only valid with capture_stdout_stderr_first=False
    flush_stdout_before=True,  # Flushes the history in blocking_shell.stdout before executing a command
    flush_stdin_before=True,  # Flushes the history in blocking_shell.stderr before executing a command
    flush_stderr_before=True,  # Flushes the history in blocking_shell.stdin before executing a command
    exitcommand="xxxCOMMANDxxxDONExxx",
    # Written using echo at the end of every command to determine when the output is finished
    capture_stdout_stderr_first=True,  # Blocks the process until the execution of a command is finished
    global_cmd=False,
    global_cmd_timeout=5,
)
# Non-blocking Subshell
# - Does not wait until stderr/stdout have finished processing.
# - Commands are base64 encoded.
# - All commands are executed within a subshell using a pipeline like base64command | base64 -d | sh.
# - For example, if you run "cd /sdcard/" and then another command like "ls," you will see the contents of the root directory '/' instead of '/sdcard'.
# - Note that 'su' is only valid for a single command.

nonblocking_subshell = AdbControl(
    adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
    device_serial=addr,
    use_busybox=False,  # Use busybox to decode base64 (if needed)
    connect_to_device=True,
    invisible=True,
    # Windows only - This option prevents the shell window from opening, e.g., when compiling the code with Nuitka.
    print_stdout=True,
    print_stderr=True,
    limit_stdout=3,  # Limit the history of shell commands (can be checked at blocking_shell.stdout)
    limit_stderr=3,  # Limit the history of shell commands (can be checked at blocking_shell.stderr)
    limit_stdin=None,  # Limit the history of shell commands (can be checked at blocking_shell.stdin)
    convert_to_83=True,  # Converts the adb path to 8.3 format on Windows
    wait_to_complete=0,  # Time to wait for command completion - only valid with capture_stdout_stderr_first=False
    flush_stdout_before=True,  # Flushes the history in blocking_shell.stdout before executing a command
    flush_stdin_before=True,  # Flushes the history in blocking_shell.stderr before executing a command
    flush_stderr_before=True,  # Flushes the history in blocking_shell.stdin before executing a command
    exitcommand="xxxCOMMANDxxxDONExxx",
    # Written using echo at the end of every command to determine when the output is finished
    capture_stdout_stderr_first=False,  # Blocks the process until the execution of a command is finished
    global_cmd=False,
    global_cmd_timeout=5,
)

# Added 9.11.2023 - Eval Shell
# - Waits until stderr/stdout have finished processing unless there is a timeout
# - Commands are written to a txt file and executed from there.
# - All commands are executed within a subshell using eval
# - stdout/stderr are transfered via netcat
# - Way faster than the other methods since it uses netcat
eval_shell = AdbControl(
    adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
    device_serial=addr,
    use_busybox=False,
    connect_to_device=True,
    invisible=True,
    print_stdout=True,
    print_stderr=True,
    limit_stdout=3,
    limit_stderr=3,  # limits the history of shellcommands - can be checked at blocking_shell.stderr
    limit_stdin=None,
    convert_to_83=True,
    wait_to_complete=0,
    flush_stdout_before=True,
    flush_stdin_before=True,
    flush_stderr_before=True,
    exitcommand="xxxCOMMANDxxxDONExxx",
    capture_stdout_stderr_first=True,
    global_cmd=True,
    global_cmd_timeout=10,
    use_eval=True,  # executes commands using eval
    eval_timeout=10,  # timeout for eval (netcat transfer)
)
executecmds = False
if executecmds:
    # The AdbControl module stays connected to an adb instance throughout its usage.
    # It continuously reads from stdout, stderr, and writes to stdin.
    # A typical way to execute adb commands is as follows:
    # adb.exe -s DEVICE shell ls /sdcard/
    # The problem with this approach is that it generates significant overhead for each command.

    # This module executes 'adb.exe -s DEVICE shell' right at the beginning when you create the instance
    # and keeps the shell open. This approach minimizes overhead, as the executable is run only once
    # and remains in a standby mode.

    # The core functionality of this module is provided by the AdbControl.execute_sh_command method.
    # Most commands are executed using this method.

    # You can use blocking_shell.execute_sh_command to run any command, and it returns a list of lists.
    # The first element is the stdout, and the second is stderr.
    stdout, stderr = blocking_shell.execute_sh_command("ls /sdcard/")
    # stderr
    # Out[5]: []
    # stdout
    # ....
    #  b'1753_mem_12c00000.bin\r\n',
    #  b'1753_mem_74d74000.bin\r\n',
    #  b'1753_mem_74ecd000.bin\r\n',
    #  b'1753_mem_77d75000.bin\r\n',
    #  b'1753_mem_ce771000.bin\r\n',
    # ...
    # If you encounter any problems with deadlocks, you can use the non-blocking version mentioned above:
    stdout, stderr = nonblocking_subshell.execute_sh_command("ls /sdcard/")

    # You don't have to create a new instance; you can temporarily switch to the non-blocking version:
    stdout, stderr = blocking_shell.execute_sh_command(
        "ls /sdcard/",
        capture_stdout_stderr_first=False,
        global_cmd=False,
        wait_to_complete=0,
    )

    # Or switch to the subshell blocking version temporarily:
    stdout, stderr = blocking_shell.execute_sh_command(
        "ls /sdcard/",
        capture_stdout_stderr_first=True,
        global_cmd=False,
        wait_to_complete=0.1,
    )

    # These are the available keyword arguments that can be used to temporarily adjust the configuration:
    # - disable_print_stdout
    # - disable_print_stderr
    # - wait_to_complete
    # - flush_stdout_before
    # - flush_stdin_before
    # - flush_stderr_before
    # - exitcommand
    # - su
    # - commandtimeout
    # - escape_filepath
    # - escape_filepath
    # - capture_stdout_stderr_first
    # - global_cmd

    # stderr
    # Out[5]: []
    # stdout
    # ....
    #  b'1753_mem_12c00000.bin\r\n',
    #  b'1753_mem_74d74000.bin\r\n',
    #  b'1753_mem_74ecd000.bin\r\n',
    #  b'1753_mem_77d75000.bin\r\n',
    #  b'1753_mem_ce771000.bin\r\n',
    # ...

    # All commands using the blocking and non-blocking subshell are converted to
    # base64 and sent to the device for decoding and execution.

    # For example, when you execute this command:
    blocking_subshell.execute_sh_command("ls /data/data")

    # It is executed as:
    # b'echo ZXhlYyAzPiYxIDQ+JjIgMT4vc2RjYXJkL3h4eHhzdGRvdXQxNjk4NzU0ODk5LjY4MjUzMzcudHh0IDI+L3NkY2FyZC94eHhzdGRlcnIxNjk4NzU0ODk5LjY4MjUzMzcudHh0CmxzIC9kYXRhL2RhdGEKZXhlYyAxPiYzIDI+JjQKY2F0IC9zZGNhcmQveHh4eHN0ZG91dDE2OTg3NTQ4OTk5LjY4MjUzMzcudHh0CmxzIC9kYXRhL2RhdGEKZXhlYyAxPiY1IDI+JjYKY2F0IC9zZGNhcmQveHh4c3RkZXJyMTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+JjYKcm0gLWYgL3NkY2FyZC94eHh4c3Rkb3V0MTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+IC9kZXYvbnVsbCAyPiYxCnJtIC1mIC9zZGNhcmQveHh4c3RkZXJyMTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+IC9kZXYvbnVsbCAyPiYxCmVjaG8geHh4Q09NTUFORHh4eERPTkV4eHgK | base64 -d | sh\n'

    # You can decode it as:
    # base64.b64decode(b'ZXhlYyAzPiYxIDQ+JjIgMT4vc2RjYXJkL3h4eHhzdGRvdXQxNjk4NzU0ODk5LjY4MjUzMzcudHh0IDI+L3NkY2FyZC94eHhzdGRlcnIxNjk4NzU0ODk5LjY4MjUzMzcudHh0CmxzIC9kYXRhL2DmRhdGEKZXhlYyAxPiYzIDI+JjQKY2F0IC9zZGNhcmQveHh4eHN0ZG91dDE2OTg3NTQ4OTk5LjY4MjUzMzcudHh0CmxzIC9kYXRhL2DmRhdGEKZXhlYyAxPiY1IDI+JjYKY2F0IC9zZGNhcmQveHh4c3RkZXJyMTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+JjYKcm0gLWYgL3NkY2FyZC94eHh4c3Rkb3V0MTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+IC9kZXYvbnVsbCAyPiYxCnJtIC1mIC9zZGNhcmQveHh4c3RkZXJyMTY5ODc1NDg5OS42ODI1MzM3LnR4dCA+IC9kZXYvbnVsbCAyPiYxCmVjaG8geHh4Q09NTUFORHh4eERPTkV4eHgK')

    # As you can see, stdout and stderr are temporarily redirected and printed at the end to ensure that the entire output is captured.
    # This is essential to avoid closing adb.exe to minimize overhead.

    # If you encounter problems or deadlocks while executing commands this way, you can execute them as non-blocking commands.
    # To do this, set the kwargs `capture_stdout_stderr_first=False` and `wait_to_complete=0`.
    # and global_cmd to false
    stdout, stderr = nonblocking_subshell.execute_sh_command(
        "ls /data/data",
        capture_stdout_stderr_first=False,
        wait_to_complete=0,
        global_cmd=False,
    )

    # This is the command that was executed non-blocking:
    # base64.b64decode(b'bHMgL2RhdGEvZGF0YQplY2hvIHh4eENPTU1BTkR4eHhET05FeHh4Cg==')

    # You can convert any command to base64 using the `AdbControl.format_adb_command` method:
    blocking_shell.format_adb_command(
        cmd="ls /sdcard/", su=False, exitcommand="DONE", errors="strict"
    )

    # You can also convert any command to base64 and execute a command for screen capture using
    # `blocking_shell.format_adb_command_screen_capture`:
    blocking_shell.format_adb_command_screen_capture(
        cmd="ls /sdcard/", su=False, exitcommand="DONE", errors="strict"
    )
    # Out[4]: b'echo bHMgL3NkY2FyZC8KZWNobyBET05FCg== | base64 -d | sh\n'

    # blocking shell commands are executed like this:
    blocking_shell.execute_sh_command(r"ls")

    # b'#!/bin/bash\nexec 2>/sdcard/errortmp16989591673106961.txt\nexec 1>/sdcard/outputtmp16989591673106961.txt\nls\nexec 1>&-\nexec 2>&-\n\necho -n -e xxxCOMMANDxxxDONExxx>> /sdcard/outputtmp16989591673106961.txt\necho -n -e xxxCOMMANDxxxDONExxx >> /sdcard/errortmp16989591673106961.txt\n'
    # for each new instance, there are new tempfiles, to delete all of them, you can use:
    blocking_shell.remove_stderr_stdout_tmpfiles_on_sdcard()

    # Using the non blocking modus is useful if you want to execute commands at the same time:

    # Creating a new AdbControl instance
    instance2 = AdbControl(
        adb_path=r"C:\Android\android-sdk\platform-tools\adb.exe",
        device_serial="127.0.0.1:5555",
        use_busybox=False,  # Use busybox to decode base64 if needed
        connect_to_device=True,
        invisible=True,
        # Windows only - Prevents the opening of a shell window when compiling the code with Nuitka, for example
        print_stdout=True,
        print_stderr=True,
        limit_stdout=3,  # Limits the history of shell commands - can be checked at blocking_shell.stdout
        limit_stderr=3,  # Limits the history of shell commands - can be checked at blocking_shell.stderr
        limit_stdin=None,  # Limits the history of shell commands - can be checked at blocking_shell.stdin
        convert_to_83=True,  # Converts the adb path to 8.3 format on Windows
        wait_to_complete=0,  # Time to wait for command completion - 0 means non blocking
        flush_stdout_before=True,  # Flushes the history in blocking_shell.stdout
        flush_stdin_before=True,  # Flushes the history in blocking_shell.stderr
        flush_stderr_before=True,  # Flushes the history in blocking_shell.stdin
        exitcommand="xxxCOMMANDxxxDONExxx",
        # Written using echo at the end of every command to determine when the output is finished
        capture_stdout_stderr_first=False,  # Doesn't block the process until the execution of a command is finished
        global_cmd=False,
        global_cmd_timeout=5,
    )

    # Execute two commands simultaneously in a non-blocking way
    # Keep in mind that the stdout/stderr list might grow even after returning
    stdout1, stderr1 = nonblocking_subshell.execute_sh_command(
        "ls -R /",
        capture_stdout_stderr_first=False,
        su=True,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout1))

    stdout2, stderr2 = instance2.execute_sh_command(
        "ls -R /sdcard/",
        capture_stdout_stderr_first=False,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout2))

    sleep(0.1)
    print(len(stdout1), len(stdout2))

    # This creates some crazy swipe effect:

    stdout1, stderr1 = nonblocking_subshell.execute_sh_command(
        "input swipe 100 300 200 800 2000",
        capture_stdout_stderr_first=False,
        su=True,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout1))

    stdout2, stderr2 = instance2.execute_sh_command(
        "input swipe 400 300 600 800 2000",
        capture_stdout_stderr_first=False,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout2))
    stdout1, stderr1 = nonblocking_subshell.execute_sh_command(
        "input swipe 100 300 200 800 2000",
        capture_stdout_stderr_first=False,
        su=True,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout1))

    stdout2, stderr2 = instance2.execute_sh_command(
        "input swipe 400 300 600 800 2000",
        capture_stdout_stderr_first=False,
        wait_to_complete=0,
        global_cmd=False,
    )
    print(len(stdout2))

    # Commands can include special characters, but spaces, quotes, etc., must be escaped:
    blocking_shell.execute_sh_command(r"cat /sdcard/bxx\ ab\ bcçc/xxx222\ d.txt")
    nonblocking_subshell.execute_sh_command(r"cat /sdcard/bxx\ ab\ bcçc/xxx222\ d.txt")
    blocking_subshell.execute_sh_command(r"cat /sdcard/bxx\ ab\ bcçc/xxx222\ d.txt")

    # You can escape characters like this. This method is used in several functions but not all,
    # as it might escape characters that shouldn't be escaped:
    from usefuladb import strip_quotes_and_escape

    blocking_shell.execute_sh_command(
        rf"cat {strip_quotes_and_escape('/sdcard/bxx ab bcçc/xxx222 d.txt')}"
    )

    # You can execute the command as bytes, but avoid using this unless necessary:
    blocking_shell.execute_sh_command(b"ls /sdcard/")
    blocking_shell.execute_sh_command(
        b"cat /sdcard/bxx\\ ab\\ bc\xc3\xa7c/xxx222\\ d.txt"
    )

    # Many adb commands are available as ready-to-use functions, so you don't have to worry about escaping and other details.
    # For example, to cat a file, you can use:
    blocking_shell.sh_cat_file(
        "/sdcard/bxx ab bcçc/xxx222 d.txt"
    )  # Escaping is done automatically, and quotes are stripped - either you escape or put it in quotes but not both :).

    # The significant advantage of using base64 encoding is the ability to execute bash scripts:
    nonblocking_subshell.execute_sh_command(
        """#!/bin/bash
    i=0
    while true; do
        i=$((i + 1))
        ls /sdcard/
        sleep 1.0
        if [ "$i" -gt 5 ]; then
            break
        fi
    done
    """
    )

    # You can also execute scripts as bytes:
    blocking_subshell.execute_sh_command(
        b"""#!/bin/bash
    i=0
    while true; do
        i=$((i + 1))
        ls /sdcard
        sleep 0.1
        if [ "$i" -gt 5 ]; then
            break
        fi
    done
    """
    )

    # Note that there is a potential risk when executing bash scripts with blocking_shell since the commands are not encoded to
    # base64. However, this risk should be manageable if you use caution and only execute trusted scripts.

    # A disadvantage of base64 is that the "cd" command, for example,
    # is only valid within one command since all commands are executed in a subshell:
    blocking_subshell.sh_change_to_dir("/sdcard/")
    # Out[12]: [[], []]
    blocking_subshell.execute_sh_command("ls")
    # This command prints the content of "/", not "/sdcard/"
    # To achieve the desired behavior, you have to use:
    blocking_subshell.execute_sh_command("cd /sdcard/ && ls")

    # To execute a command with superuser (su) privileges:
    blocking_subshell.execute_sh_command("ls /data/data")  # not working
    # Out[3]: [[], [b'ls: /data/data: Permission denied\r\n']]

    blocking_subshell.execute_sh_command("ls /data/data", su=True)  # working now
    # Out[4]:
    # [[b'android\r\n',
    #   b'android.ext.services\r\n',
    #   b'com.android.adbkeyboard\r\n',
    #   b'com.android.bookmarkprovider\r\n',
    #   b'com.android.camera2\r\n',

    # You can execute a shell script with superuser privileges in the same way:
    blocking_shell.execute_sh_command(
        b"""
    #!/bin/bash
    i=0
    while true; do
        i=$((i + 1))
        ls /data/data
        sleep 0.1
        if [ "$i" -gt 5 ]; then
            break
        fi
    done
    """,
        su=True,
    )

    # Piping is also possible:
    blocking_shell.execute_sh_command(
        r'dumpsys -t 1000000 | grep -E "com\.google\.android.{0,10}"'
    )

    # Here are some additional methods I've added to save time when working with ADB.
    # These methods can be used to perform various operations.

    # Create a new file using the sh_touch method:
    blocking_shell.sh_touch(
        "/sdcard/i dont exist yet/me neither/i have spëçiäl chars.txt"
    )
    # Out[6]: [[], []]
    nonblocking_subshell.sh_touch(
        "/sdcard/i dont exist yet/me neither/i have spëçiäl chars2.txt"
    )
    # Out[7]: [[], []]
    blocking_subshell.sh_touch(
        "/sdcard/i dont exist yet/me neither/i have spëçiäl chars3.txt"
    )
    # Out[8]: [[], []]

    # Append a line to an existing file using the sh_append_line_to_file method:
    blocking_shell.sh_append_line_to_file(
        "did it work?", "/sdcard/i dont exist yet/me neither/i have spëçiäl chars.txt"
    )
    # Out[7]: [[b'did it work?\r\n'], []]

    # Read the content of a file using the sh_cat_file method:
    file_content = blocking_shell.sh_cat_file(
        "/sdcard/i dont exist yet/me neither/i have spëçiäl chars.txt"
    )
    # Out[8]: b'did it work?\n'

    # To perform these operations with superuser (su) privileges, you can add the su=True parameter:
    blocking_shell.sh_touch(
        "/data/data/i dont exist yet/me neither/i have spëçiäl chars.txt", su=True
    )
    blocking_shell.sh_append_line_to_file(
        "did it work?",
        "/data/data/i dont exist yet/me neither/i have spëçiäl chars.txt",
        su=True,
    )

    catstuff = blocking_shell.sh_cat_file(
        "/data/data/i dont exist yet/me neither/i have spëçiäl chars.txt", su=True
    )
    # Out[10]: b'did it work?\n'
    # As you might have noticed, blocking_shell.sh_cat_file returns binary data, and \r\n is already replaced with \n.
    # Due to the post-processing involved, it's not recommended to use nonblocking_subshell in this case, as the data
    # might not be complete.
    catstuff = nonblocking_subshell.sh_cat_file(
        "/data/data/i dont exist yet/me neither/i have spëçiäl chars1.txt", su=True
    )

    # List the contents of a folder with superuser privileges:
    blocking_shell.sh_ls_folder("/data/data/i dont exist yet/me neither/", su=True)
    # Out[11]: [[b'i have sp\xc3\xab\xc3\xa7i\xc3\xa4l chars.txt\r\n'], []]

    # Additional methods to open various Android settings:
    blocking_shell.sh_open_date_settings()
    blocking_shell.sh_open_settings()
    blocking_shell.sh_open_application_development_settings()
    blocking_shell.sh_open_location_source_settings()
    blocking_shell.sh_open_memory_card_settings()
    blocking_shell.sh_open_locale_settings()
    blocking_shell.sh_open_search_settings()
    blocking_shell.sh_open_account_sync_settings()
    blocking_shell.sh_open_display_settings()
    blocking_shell.sh_open_input_method_settings()
    blocking_shell.sh_open_sound_settings()
    blocking_shell.sh_open_wifi_settings()
    blocking_shell.sh_open_application_settings()
    blocking_shell.sh_open_account_sync_settings_add_account()
    blocking_shell.sh_open_manage_applications_settings()
    blocking_shell.sh_open_sync_settings()
    blocking_shell.sh_open_dock_settings()
    blocking_shell.sh_open_add_account_settings()
    blocking_shell.sh_open_security_settings()
    blocking_shell.sh_open_device_info_settings()
    blocking_shell.sh_open_wireless_settings()
    blocking_shell.sh_open_system_update_settings()
    blocking_shell.sh_open_manage_all_applications_settings()
    blocking_shell.sh_open_data_roaming_settings()
    blocking_shell.sh_open_apn_settings()
    blocking_shell.sh_open_user_dictionary_settings()
    blocking_shell.sh_open_voice_input_output_settings()
    blocking_shell.sh_open_tts_settings()
    blocking_shell.sh_open_wifi_ip_settings()
    blocking_shell.sh_open_web_search_settings()
    blocking_shell.sh_open_bluetooth_settings()
    blocking_shell.sh_open_airplane_mode_settings()
    blocking_shell.sh_open_internal_storage_settings()
    blocking_shell.sh_open_accessibility_settings()
    blocking_shell.sh_open_quick_launch_settings()
    blocking_shell.sh_open_privacy_settings()

    # Display orientation using ScreenOrientation: https://developer.android.com/reference/androidx/browser/trusted/ScreenOrientation
    display_orientation = blocking_shell.sh_get_display_orientation()
    # Out[14]: 0

    # Additional keypress events methods have been added for convenience:

    blocking_shell.k_app_switch(longpress=True)
    blocking_shell.k_app_switch(longpress=True)
    blocking_shell.k_app_switch(longpress=False)
    blocking_shell.k_app_switch(longpress=False)
    blocking_shell.k_app_switch()
    blocking_shell.k_brightness_down()
    blocking_shell.k_brightness_up()
    blocking_shell.k_contacts()
    blocking_shell.k_copy()
    blocking_shell.k_cut()
    blocking_shell.k_home()
    blocking_shell.k_page_down()
    blocking_shell.k_page_up()
    blocking_shell.k_paste()
    blocking_shell.k_power()
    blocking_shell.k_search()
    blocking_shell.k_sleep()
    blocking_shell.k_tab()
    blocking_shell.k_volume_down()
    blocking_shell.k_volume_up()
    blocking_shell.k_volume_mute()
    blocking_shell.k_wakeup()

    # You can execute any other keypress like this:
    blocking_shell.keyevents.KEYCODE_P.longpress.keyboard()
    blocking_shell.keyevents.KEYCODE_PAGE_DOWN.press.keyboard()
    blocking_shell.keyevents.KEYCODE_P.longpress.touchpad()
    blocking_shell.keyevents.KEYCODE_P.longpress.gamepad()
    blocking_subshell.keyevents.KEYCODE_P.longpress.touchpad()
    nonblocking_subshell.keyevents.KEYCODE_P.longpress.touchpad()

    # Push files with spaces and special characters into [non-]existing folders.
    # This method sends the data using stdin and base64 encoding, rather than using adb.exe push.

    blocking_shell.push(
        r"C:\Users\hansc\Downloads\RobloxPlayerInstaller (6).exe",
        "/sdcard/not existing path/çççö",
    )
    # Note: The non-blocking subshell is not recommended for this operation.
    # You can use the blocking_subshell for file pushes.
    nonblocking_subshell.push(
        r"C:\Users\hansc\Downloads\RobloxPlayerInstaller (6).exe",
        "/sdcard/not existing path/çççö1",
    )
    blocking_subshell.push(
        r"C:\Users\hansc\Downloads\RobloxPlayerInstaller (6).exe",
        "/sdcard/not existing path/çççö2",
    )
    # Check if the file was successfully created in the specified folder:
    blocking_shell.sh_ls_folder("/sdcard/not existing path/çççö")
    # Out[23]: [[b'RobloxPlayerInstaller (6).exe\r\n'], []]

    # Check if the file exists using sh_file_exists method:
    file_exists = blocking_shell.sh_file_exists(
        r"/sdcard/not existing path/çççö/RobloxPlayerInstaller (6).exe"
    )
    # Out[24]: True

    # Note: Using the non-blocking version is not recommended for checking file existence.
    # It may result in a early response, leading to potential errors.
    # Instead, use the blocking_subshell for file existence checks.
    file_exists = blocking_subshell.sh_file_exists(
        r"/sdcard/not existing path/çççö/RobloxPlayerInstaller (6).exe"
    )
    # ....
    #     return bool(int(stdout[0].strip().decode("utf-8")))
    #                     ~~~~~~^^^
    # IndexError: list index out of range
    # 1

    # The file can also be pulled, but it is essentially the same as what cat is doing:
    # Don't use the non blocking variation here!
    filedata = blocking_shell.pull(
        r"/sdcard/not existing path/çççö/RobloxPlayerInstaller (6).exe"
    )
    with open("c:\\robloxinstall.exe", mode="wb") as f:
        f.write(filedata)

    # Remove the file using sh_remove_file method:
    blocking_shell.sh_remove_file(
        r"/sdcard/not existing path/çççö/RobloxPlayerInstaller (6).exe"
    )
    blocking_subshell.sh_remove_file(
        r"/sdcard/not existing path/çççö1/RobloxPlayerInstaller (6).exe"
    )
    # This is a great usecase for the non blocking version if don't care much about the stdout/stderr.
    nonblocking_subshell.sh_remove_file(
        r"/sdcard/not existing path/çççö2/RobloxPlayerInstaller (6).exe"
    )

    # Check if the file was successfully removed:
    blocking_shell.sh_file_exists(
        r"/sdcard/not existing path/çççö/RobloxPlayerInstaller (6).exe"
    )
    # Out[12]: False

    # Rescan a single file to show up in the gallery:
    blocking_shell.push(
        r"C:\asgasdfasdfasdf.png",
        "/sdcard/Download",
    )
    blocking_shell.sh_rescan_one_media("/sdcard/Download/asgasdfasdfasdf.png")

    # You can also push and pull entire folders:
    blocking_shell.pull_folder("/sdcard/Download", "c:\\babababaxx")
    # or 
    blocking_shell.sh_pull_folder_with_cat("/sdcard/Download", "c:\\babababaxx")
    

    # Push a folder from the local machine to the device:
    blocking_shell.push_folder(r"C:\qqqqqqqqqqqq", "/sdcard/")

    # You might encounter some errors, but you can ignore them, as 'tar' tries to execute 'chown,' which is not permitted.
    # Out[20]:
    # ([b'./\r\n',
    #   b'./asgasdfasdfasdf.png\r\n',
    #   b'./ba.html\r\n',
    #   b'./baba.png\r\n',
    #   b'./babaxx2.mhtml\r\n',
    #   b'./bibi.png\r\n',
    #   b'./bibixx.png\r\n',
    #   b'./datetmp.log\r\n',
    #   b'./tmp5j75s57u.tar\r\n'],
    #  [b"tar: chown 0:0 '.': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './asgasdfasdfasdf.png': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './ba.html': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './baba.png': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './babaxx2.mhtml': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './bibi.png': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './bibixx.png': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './datetmp.log': Operation not permitted\r\n",
    #   b"tar: chown 0:0 './tmp5j75s57u.tar': Operation not permitted\r\n",
    #   b'rm: tmpqp5_mrdt.tar: No such file or directory\r\n'])

    # List users on the device:
    users = blocking_shell.sh_list_users()
    # ['UserInfo{0:Owner:13} running']

    # NOTIFICATIONS:

    # Enable and disable heads-up notifications:
    blocking_shell.sh_enable_heads_up_notifications()
    blocking_shell.sh_disable_heads_up_notifications()

    # Open the camera to take a photo:
    blocking_shell.sh_still_image_camera()
    # Out[13]: [[b'Starting: Intent { act=android.media.action.STILL_IMAGE_CAMERA }\r\n'], []]

    # Make a call:
    blocking_shell.sh_make_call("+5511989782756")

    # Dumpsys:

    blocking_shell.sh_dumpsys_activity_settings()
    blocking_shell.sh_dumpsys_activity_allowed_associations()
    blocking_shell.sh_dumpsys_activity_intents()
    blocking_shell.sh_dumpsys_activity_broadcasts()
    blocking_shell.sh_dumpsys_activity_broadcast_stats()
    blocking_shell.sh_dumpsys_activity_providers()
    blocking_shell.sh_dumpsys_activity_permissions()
    blocking_shell.sh_dumpsys_activity_services()
    blocking_shell.sh_dumpsys_activity_recents()
    blocking_shell.sh_dumpsys_activity_lastanr()
    blocking_shell.sh_dumpsys_activity_starter()
    blocking_shell.sh_dumpsys_activity_activities()
    blocking_shell.sh_dumpsys_activity_exit_info()
    blocking_shell.sh_dumpsys_activity_processes()
    blocking_shell.sh_dumpsys_activity_lru()

    # Dump package information for a specific package (e.g., com.roblox.client):
    blocking_shell.sh_pm_dump("com.roblox.client")

    # Screen-related operations:

    # Get the screen width and height:
    w, h = blocking_shell.sh_get_wm_size()
    # this one is better:
    width, height = blocking_shell.sh_get_resolution()

    # Change the screen resolution to 960x540:
    blocking_shell.sh_change_wm_size(960, 540)

    # Reset the screen resolution to its default:
    blocking_shell.sh_wm_reset_size()

    # Get the current screen density:
    blocking_shell.sh_get_wm_density()

    # Change the screen density to 160:
    blocking_shell.sh_change_wm_density(160)

    # Reset the screen density to its default:
    blocking_shell.sh_wm_reset_density()

    # List device features and present working directory (pwd):
    blocking_shell.sh_list_features()
    blocking_shell.sh_pwd()

    # Create a directory with nested subdirectories on the device:
    blocking_shell.sh_mkdir("/sdcard/bobo/baba/bibix/not existing/me neither")
    # Out[7]: [[], []]

    # List the contents of a specific folder on the device:
    blocking_shell.sh_ls_folder("/sdcard/bobo/baba/bibix")
    # Out[6]: [[b'not existing\r\n'], []]

    # Create a directory and change into it (not necessary if the next command is not going to be launched in the folder):
    blocking_shell.sh_mkdir_and_cd("/sdcard/bibi")

    # Check if a folder exists on the device:
    folder_exists = blocking_shell.sh_is_folder("/sdcard/bobo/baba/bibix/")
    # Out[4]: True

    # Exit from the superuser (su) shell (only valid for blocking_shell):
    blocking_shell.exit_from_su_shell()

    # List available services on the device:
    blocking_shell.sh_list_services()
    # [[b'Found services:\r\n',
    #   b'0\tsip: [android.net.sip.ISipService]\r\n',
    #   b'1\tcarrier_config: [com.android.internal.telephony.ICarrierConfigLoader]\r\n',

    # Open a URL in a web browser:
    blocking_shell.sh_open_url("https://www.google.com")
    # Out[7]: [[b'Starting: Intent { act=android.intent.action.VIEW dat=https://www.google.com/... }\r\n'], []]

    # Get the NTP (Network Time Protocol) server information:
    blocking_shell.sh_get_ntp_server()
    # Out[8]: [[b'null\r\n'], []]

    # List installed packages on the device:
    blocking_shell.sh_pm_list_packages_f_i_u()
    blocking_shell.sh_pm_list_packages_3()
    blocking_shell.sh_pm_list_packages_s()

    # Show mounted devices on the device:
    blocking_shell.sh_mount()

    # The 'su' (superuser) mode is automatically set to true here because it is necessary to obtain this data.
    # This applies to some other methods as well.

    # Get IMEI, IMSI, and SIM information (valid until Android 9):
    imei, imsi, sim = blocking_shell.get_imei_imsi_sim()
    # For devices with more than one SIM card, get IMEIs:
    a, b = blocking_shell.get_imeis_multidevices()
    # Get IMEI information for Android 14 (but also works on Android 9):
    imei = blocking_shell.get_imei_android_14()

    # Verify that the file copy operations were successful:
    blocking_shell.sh_ls_folder("/sdcard/Download2")
    # Out[21]:
    # [[b'Nearby Share\r\n',
    #   b'asgasdfasdfasdf.png\r\n',
    #   b'ba.html\r\n',
    #   b'baba.png\r\n',
    #   b'babaxx2.mhtml\r\n',
    #   b'bibi.png\r\n',
    #   b'bibixx.png\r\n',
    #   b'datetmp.log\r\n',
    #   b'tmp5j75s57u.tar\r\n',
    #   b'tmpqp5_mrdt.tar\r\n'],
    #  []]

    # Change the display orientation to the specified value (in this case, new_orientation=1).
    blocking_shell.sh_change_display_orientation(new_orientation=1)

    # Perform random actions on the specified app:
    blocking_shell.sh_do_random_actions(
        p=("com.spotify.music",),  # Package name for the target app
        c=(),  # Use this to specify component
        v=10,  # Number of random actions to perform
        # Set other options as needed to control the behavior of random actions.
    )
    blocking_shell.sh_do_random_actions(
        p=("com.spotify.music",),
        c=(),
        v=10,
        ignore_crashes=False,
        ignore_timeouts=False,
        ignore_security_exceptions=False,
        monitor_native_crashes=False,
        ignore_native_crashes=False,
        kill_process_after_error=False,
        hprof=False,
        match_description="",
        pct_touch=-1,
        pct_motion=-1,
        pct_trackball=-1,
        pct_syskeys=-1,
        pct_nav=-1,
        pct_majornav=-1,
        pct_appswitch=-1,
        pct_flip=-1,
        pct_anyevent=-1,
        pct_pinchzoom=-1,
        pct_permission=-1,
        pkg_blacklist_file="",
        pkg_whitelist_file="",
        wait_dbg=False,
        dbg_no_events=False,
        setup="",
        port=-1,
        s=-1,
        throttle_start=-1,
        throttle_end=-1,
        randomize_throttle=False,
        profile_wait=-1,
        device_sleep_time=-1,
        randomize_script=False,
        script_log=False,
        bugreport=False,
        periodic_bugreport=False,
        permission_target_system=False,
    )

    # Start the "com.android.chrome" package (launch the Chrome app).
    blocking_shell.sh_start_package("com.android.chrome")

    # Expand the notifications panel and settings panel.
    blocking_shell.sh_expand_notifications()
    blocking_shell.sh_expand_settings()

    # Resolve activity details for the "com.android.chrome" package.
    stdout, stderr = blocking_shell.sh_resolve_activity("com.android.chrome")
    # Out[16]:
    # [b'priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true\r\n',
    #  b'ActivityInfo:\r\n',
    #  b'  name=com.google.android.apps.chrome.Main\r\n',
    #  b'  packageName=com.android.chrome\r\n',
    #  b'  splitName=chrome\r\n',
    #  b'  enabled=true exported=true directBootAw

    # The result is a list of information about the specified activity.

    # Resolve a brief summary of activity details for the "com.android.chrome" package.
    stdout, stderr = blocking_shell.sh_resolve_activity_brief("com.android.chrome")

    # List permission groups on the device.
    blocking_shell.sh_list_permission_groups()
    # Out[14]:
    # [[b'permission group:com.google.android.gms.permission.CAR_INFORMATION\r\n',
    #   b'permission group:android.permission-group.CONTACTS\r\n',
    #   b'permission group:android.permission-group.PHONE\r\n',

    # Dump the window manager state.
    blocking_shell.sh_dumpsys_window()

    # Check if the screen is locked.
    blocking_shell.sh_is_screen_locked()
    # Out[12]: False

    # Simulate a tap at coordinates (500, 500)
    blocking_shell.sh_input_tap(500, 500)

    # Simulate a tap using the DPAD controller at coordinates (500, 500)
    blocking_shell.sh_input_dpad_tap(500, 500)

    # Simulate a tap using the keyboard at coordinates (500, 500)
    blocking_shell.sh_input_keyboard_tap(500, 500)

    # Simulate a tap using the mouse at coordinates (500, 500)
    blocking_shell.sh_input_mouse_tap(500, 500)

    # Simulate a tap using the touchpad at coordinates (500, 500)
    blocking_shell.sh_input_touchpad_tap(500, 500)

    # Simulate a tap using a gamepad at coordinates (500, 500)
    blocking_shell.sh_input_gamepad_tap(500, 500)

    # Simulate a tap using touch navigation at coordinates (500, 500)
    blocking_shell.sh_input_touchnavigation_tap(500, 500)

    # Simulate a tap using a joystick at coordinates (500, 500)
    blocking_shell.sh_input_joystick_tap(500, 500)

    # Simulate a tap using the touchscreen at coordinates (500, 500)
    blocking_shell.sh_input_touchscreen_tap(500, 500)

    # Simulate a tap using a stylus at coordinates (500, 500)
    blocking_shell.sh_input_stylus_tap(500, 500)

    # Simulate a tap using a trackball at coordinates (500, 500)
    blocking_shell.sh_input_trackball_tap(500, 500)

    # Simulate typing "bibib" using the DPAD input method
    blocking_shell.sh_input_dpad_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using the keyboard input method
    blocking_shell.sh_input_keyboard_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "ççççç" using the keyboard input method and remove accents
    blocking_shell.sh_input_keyboard_text(
        "ççççç", sleeptime=(0.0, 0.0), remove_accents=True
    )

    # Simulate typing "bibib" using the mouse input method
    blocking_shell.sh_input_mouse_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using the touchpad input method
    blocking_shell.sh_input_touchpad_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using a gamepad input method
    blocking_shell.sh_input_gamepad_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using touch navigation input method
    blocking_shell.sh_input_touchnavigation_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using a joystick input method
    blocking_shell.sh_input_joystick_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using the touchscreen input method
    blocking_shell.sh_input_touchscreen_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using a stylus input method
    blocking_shell.sh_input_stylus_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    # Simulate typing "bibib" using a trackball input method
    blocking_shell.sh_input_trackball_text(
        "bibib", sleeptime=(0.0, 0.0), remove_accents=False
    )

    blocking_shell.sh_input_dpad_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_dpad_drag_and_drop(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_dpad_roll(x=10, y=300)
    blocking_shell.sh_input_keyboard_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_keyboard_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_keyboard_roll(x=10, y=300)
    blocking_shell.sh_input_mouse_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_mouse_drag_and_drop(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_mouse_roll(x=10, y=300)
    blocking_shell.sh_input_touchpad_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_touchpad_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_touchpad_roll(x=10, y=300)
    blocking_shell.sh_input_gamepad_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_gamepad_drag_and_drop(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_gamepad_roll(x=10, y=300)
    blocking_shell.sh_input_touchnavigation_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_touchnavigation_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_touchnavigation_roll(x=10, y=300)
    blocking_shell.sh_input_joystick_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_joystick_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_joystick_roll(x=10, y=300)
    blocking_shell.sh_input_touchscreen_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_touchscreen_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_touchscreen_roll(x=10, y=300)
    blocking_shell.sh_input_stylus_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_stylus_drag_and_drop(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_stylus_roll(x=10, y=300)
    blocking_shell.sh_input_trackball_swipe(x0=300, y0=100, x1=500, y1=500, t=1.0)
    blocking_shell.sh_input_trackball_drag_and_drop(
        x0=300, y0=100, x1=500, y1=500, t=1.0
    )
    blocking_shell.sh_input_trackball_roll(x=10, y=300)

    # Simulate a long tap using the DPAD input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_dpad_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using the keyboard input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_keyboard_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using the mouse input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_mouse_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using the touchpad input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_touchpad_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using a gamepad input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_gamepad_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using touch navigation input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_touchnavigation_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using a joystick input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_joystick_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using the touchscreen input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_touchscreen_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using a stylus input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_stylus_longtap(x=304, y=360, t=1.0)

    # Simulate a long tap using a trackball input method at coordinates (304, 360) for 1.0 seconds
    blocking_shell.sh_input_trackball_longtap(x=304, y=360, t=1.0)

    # A little file manager
    # Get a dictionary of files and folders in the '/sdcard/Download' directory
    filedict = blocking_shell.get_file_dict("/sdcard/Download")

    # filedict
    # Out[4]:
    # {'f6': {'file_size': 12288,
    #   'is_file': False,
    #   'is_folder': True,
    #   'is_link': False,
    #   'is_character_device_file': False,
    #   'is_block_device_file': False,
    #   'is_named_pipe': False,
    #   'is_socket': False,
    #   'owner_read': True,
    #   'owner_write': True,
    #   'owner_exec': True,
    #   'group_read': True,
    #   'group_write': True,
    #   'group_exec': True,
    #   'others_read': False,
    #   'others_write': False,
    #   'others_exec': True,
    #   'file_permissions': 'drwxrwx--x',
    #   'user_owner': 'root',
    #   'group': 'sdcard_rw',
    #   'modification_time': 1698766942,
    #   'path': '/sdcard/Download',
    #   'folder': '/sdcard',
    #   'pure_path': 'Download',
    #   'cat_file': (),
    #   'remove': (),
    #   'rename': (),
    #   'grep': ()},
    #  'f190907': {'file_size': 6147735,
    #   'is_file': True,
    #   'is_folder': False,
    #   'is_link': False,
    #   'is_character_device_file': False,
    #   'is_block_device_file': False,
    #   'is_named_pipe': False,
    #   'is_socket': False,
    #   'owner_read': True,
    #   'owner_write': True,
    #   'owner_exec': False,
    #   'group_read': True,
    #   'group_write': True,
    #   'group_exec': False,
    #   'others_read': False,
    #   'others_write': False,
    #   'others_exec': False,
    #   'file_permissions': '-rw-rw----',
    #   'user_owner': 'root',
    #   'group': 'sdcard_rw',
    #   'modification_time': 1698268016,
    #   'path': '/sdcard/Download/babaxx2.mhtml',
    #   'folder': '/sdcard/Download',
    #   'pure_path': 'babaxx2.mhtml',
    #   'cat_file': (),
    #   'remove': (),
    #   'rename': (),
    #   'grep': ()},

    # Iterate through files and folders in the dictionary
    for filename, file_info in filedict.items():
        if file_info["is_file"]:
            # For each file, print its contents using the cat_file() method
            print(file_info.cat_file())

        # Alternatively, you can search for files matching a regex pattern (e.g., '.mhtml')
        if file_info["is_file"] and file_info.regex_search(r"\.mhtml"):
            print(file_info.cat_file())

        # You can also use the grep() method to search for specific text within files
        if file_info["is_file"] and file_info.regex_search(r"\.mhtml"):
            print(file_info.grep("Odds"))

        # You can also rename and remove files and folders as needed

    # Change the permissions of all files in the '/sdcard/Download' directory to 644 (needs su)
    blocking_shell.chmod_all_files_in_folder("/sdcard/Download", 644)

    # Copy the entire '/sdcard/Download' directory to another location, e.g., '/sdcard/Download8'
    # Ignore chown errors if they occur
    # Out[37]:
    # [[b'./\r\n',
    #   b'./babaxx2.mhtml\r\n',
    #   b'./bibi.png\r\n',
    #   b'./ba.html\r\n',
    #   b'./asgasdfasdfasdf.png\r\n',
    #   b'./baba.png\r\n',
    #   b'./bibixx.png\r\n',
    #   b'./datetmp.log\r\n',
    #   b'./tmp5j75s57u.tar\r\n'],
    #  [b"tar: chown 0:1015 '.': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './babaxx2.mhtml': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './bibi.png': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './ba.html': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './asgasdfasdfasdf.png': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './baba.png': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './bibixx.png': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './datetmp.log': Operation not permitted\r\n",
    #   b"tar: chown 0:1015 './tmp5j75s57u.tar': Operation not permitted\r\n"]]

    blocking_shell.sh_ls_folder("/sdcard/Download9")
    # Out[39]:
    # [[b'asgasdfasdfasdf.png\r\n',
    #   b'ba.html\r\n',
    #   b'baba.png\r\n',
    #   b'babaxx2.mhtml\r\n',
    #   b'bibi.png\r\n',
    #   b'bibixx.png\r\n',
    #   b'datetmp.log\r\n',
    #   b'tmp5j75s57u.tar\r\n'],
    #  []]

    # Normalize the text 'bibixxççx' and send it as a single input.
    blocking_shell.input_text(
        "bibixxççx", remove_accents=True, sleep_after_letter=(0, 0)
    )

    # Send each letter of 'bibixxççx' individually with a sleep interval between letters.
    blocking_shell.input_text(
        "bibixxççx", remove_accents=True, sleep_after_letter=(0, 1)
    )

    # Install the ADB Keyboard app, which allows you to send Unicode characters. "https://github.com/senzhk/ADBKeyBoard/raw/master/ADBKeyboard.apk" and installs it
    blocking_shell.install_adb_keyboard()

    # Send the text 'bababöäß' using the ADB Keyboard app.
    blocking_shell.input_text_adbkeyboard("bababöäß")

    # Disable the current keyboard.
    blocking_shell.disable_keyboard()

    # Enable the previously installed ADB Keyboard.
    blocking_shell.enable_keyboard()

    # Re-enable the ADB Keyboard for sending Unicode characters.
    blocking_shell.enable_adbkeyboard()

    # Get the active keyboard and verify that it's 'com.android.adbkeyboard/.AdbIME'.
    blocking_shell.get_active_keyboard()

    # Disable the ADB Keyboard, which will revert to the default keyboard.
    blocking_shell.disable_keyboard()

    # Enable touch animation on the device.
    blocking_shell.sh_show_touches()

    # Disable touch animation, which is better for automation purposes.
    blocking_shell.sh_show_touches_not()

    # Disable printing of standard output.
    blocking_shell.disable_stdout_print()

    # Enable printing of standard error.
    blocking_shell.enable_stderr_print()

    # Enable printing of standard output.
    blocking_shell.enable_stdout_print()

    # Get activity element dump in CSV format, which is useful for automation with multiple devices.
    # The more you disable 1->0, the faster it gets
    blocking_shell.get_activity_element_dump(
        defaultvalue="null",
        stripline=1,
        with_class=1,
        with_mid=1,
        with_hashcode=1,
        with_elementid=1,
        with_visibility=1,
        with_focusable=1,
        with_enabled=1,
        with_drawn=1,
        with_scrollbars_horizontal=1,
        with_scrollbars_vertical=1,
        with_clickable=1,
        with_long_clickable=1,
        with_context_clickable=1,
        with_pflag_is_root_namespace=1,
        with_pflag_focused=1,
        with_pflag_selected=1,
        with_pflag_prepressed=1,
        with_pflag_hovered=1,
        with_pflag_activated=1,
        with_pflag_invalidated=1,
        with_pflag_dirty_mask=1,
    )

    # Much faster and usually enough to identify elements
    blocking_shell.get_activity_element_dump(
        defaultvalue="null",
        stripline=1,
        with_class=1,
        with_mid=0,
        with_hashcode=0,
        with_elementid=0,
        with_visibility=0,
        with_focusable=0,
        with_enabled=0,
        with_drawn=0,
        with_scrollbars_horizontal=0,
        with_scrollbars_vertical=0,
        with_clickable=0,
        with_long_clickable=0,
        with_context_clickable=0,
        with_pflag_is_root_namespace=0,
        with_pflag_focused=0,
        with_pflag_selected=0,
        with_pflag_prepressed=0,
        with_pflag_hovered=0,
        with_pflag_activated=0,
        with_pflag_invalidated=0,
        with_pflag_dirty_mask=0,
    )
    # Output from get_activity_element_dump is a CSV format representing activity elements.

    # [b'IS_ACTIVE,ELEMENT_INDEX,START_X,START_Y,CENTER_X,CENTER_Y,AREA,END_X,END_Y,WIDTH,HEIGHT,START_X_RELATIVE,START_Y_RELATIVE,END_X_RELATIVE,END_Y_RELATIVE,PARENTSINDEX,ELEMENT_ID,MID,HASHCODE,VISIBILITY,FOCUSABLE,ENABLED,DRAWN,SCROLLBARS_HORIZONTAL,SCROLLBARS_VERTICAL,CLICKABLE,LONG_CLICKABLE,CONTEXT_CLICKABLE,CLASSNAME,PFLAG_IS_ROOT_NAMESPACE,PFLAG_FOCUSED,PFLAG_SELECTED,PFLAG_PREPRESSED,PFLAG_HOVERED,PFLAG_ACTIVATED,PFLAG_INVALIDATED,PFLAG_DIRTY_MASK,LINE_STRIPPED\r\n',
    #  b'"0","0","0","0","800","450","1440000","1600","900","1600","900","0","0","1600","900","|","null","9536b93","null","I","null","E","D","null","null","null","null","null","rB1","null","null","null","null","null","null","I","null","rB1{9536b93 I.ED..... ......I. 0,0-1600,900"\r\n',
    #  b'"800","1","0","0","800","450","1440000","1600","900","1600","900","0","0","1600","900","|","null","e911b96","null","V","null","E","null","null","null","null","null","null","android.widget.LinearLayout","null","null","null","null","null","null","null","null","android.widget.LinearLayout{e911b96 V.E...... ........ 0,0-1600,900"\r\n',
    #  b'"800","2","0","0","0","0","0","0","0","0","0","0","0","0","0","|1|","android:id/action_mode_bar_stub","9fdc7d0","102018a","G","null","E","null","null","null","null","null","null","android.view.ViewStub","null","null","null","null","null","null","I","null","android.view.ViewStub{9fdc7d0 G.E...... ......I. 0,0-0,0 #102018a android:id/action_mode_bar_stub"\r\n',
    #

    # Get a UI Automator element dump in CSV format. The device does the parsing using a shell script.
    # Output is a CSV that can be read using pandas.
    blocking_shell.get_uiautomator_element_dump(defaultvalue="null")
    # [b'INDEX,TEXT,RESOURCE_ID,CLASS,PACKAGE,CONTENT_DESC,CHECKABLE,CHECKED,CLICKABLE,ENABLED,FOCUSABLE,FOCUSED,SCROLLABLE,LONG_CLICKABLE,PASSWORD,SELECTED,BOUNDS,STARTX,ENDX,STARTY,ENDY,CENTER_X,CENTER_Y,AREA,WIDTH,HEIGHT\r\n',
    #  b'"null","null","null","android.widget.FrameLayout","com.android.chrome","null","false","false","false","true","false","false","false","false","false","false","0 0 1600 900","0","1600","0","900","800","450","1440000","1600","900"\r\n',
    #  b'"android:id/content","null","null","android.widget.LinearLayout","com.android.chrome","null","false","false","false","true","false","false","false","false","false","false","0 0 1600 900","0","1600","0","900","800","450","1440000","1600","900"\r\n',

    # Obtain a list of all available keys for the sendevent command.
    blocking_shell.get_all_sendevent_keys()
    # [[1, 'KEY_RESERVED'],
    #    [2, 'KEY_W'],
    #    [3, 'KEY_I'],
    #    [4, 'KEY_F6'],
    #    [5, 'KEY_KP9'],
    #    [6, 'KEY_102ND'],
    #    [7, 'KEY_VOLUMEUP'],
    #    [8, 'KEY_CALC'],
    #    [9, 'KEY_PROG3'],
    #    [10, 'BTN_DIGI'],
    #    [11, 'BTN_TOUCH'],
    #    [12, 'KEY_OK'],

    # You can also use sendevents to send keystrokes (needs su)
    blocking_shell.parse_sendevent_keys()  # need to be parsed first
    # After the parsing, they can be used like this:
    blocking_shell.keyevents_sendevent.event3.KEY_A(
        0.8, wait_to_complete=0, capture_stdout_stderr_first=False
    )
    blocking_shell.keyevents_sendevent.event3.KEY_B(
        1, wait_to_complete=0, capture_stdout_stderr_first=False
    )

    # Get a memory dump from a specific process (e.g., process with PID 1979). Note that this may take some time to complete.
    blocking_shell.get_memdump_from_process(1979)

    # Start a subprocess with elevated privileges (su) and attempt to kill all user-started processes.
    # This doesn't always work
    blocking_shell.save_a_stuck_shell()

    # Check if the keyboard is currently shown.
    blocking_shell.is_keyboard_shown()

    # Check if the ADB server is still alive.
    blocking_shell.isalive()

    # Access keyevents for different input methods (gamepad and keyboard).
    blocking_shell.keyevents.KEYCODE_E.press.gamepad()
    blocking_shell.keyevents.KEYCODE_E.press.keyboard()

    # Kill the ADB instance.
    blocking_shell.kill_proc()

    # List all listening ports along with their associated PIDs.
    blocking_shell.list_all_listening_ports_and_pid()

    # Open an ADB shell in cmd.exe.
    blocking_shell.open_adb_shell()

    # You can use the rgb_values_of_area function to obtain the RGB values in a specified area on the screen.
    # This function retrieves the RGB values within the defined area (between coordinates (x1, y1) and (x2, y2)). The result includes a list of XYRGB
    # This calculation is done directly on the device, no screenshots are transferred.
    coordsofcolours = blocking_shell.rgb_values_of_area(200, 200, 220, 320)
    #  XYRGB(x=215, y=249, r=254, g=254, b=254),
    #  XYRGB(x=216, y=249, r=254, g=254, b=254),
    #  XYRGB(x=217, y=249, r=254, g=254, b=254),
    #  XYRGB(x=218, y=249, r=254, g=254, b=254),
    #  XYRGB(x=219, y=249, r=254, g=254, b=254),

    # Some stuff for scripting:
    # Calculate the absolute value of a number.
    blocking_shell.sh_abs_value_of_number(-444)

    # Use an AWK calculator to perform mathematical calculations.
    blocking_shell.sh_awk_calculator("13.5*3")

    # Convert a string from uppercase to lowercase.
    blocking_shell.sh_upperstring_to_lowerstring("OOOXxx")

    # Extract a substring from a given string.
    blocking_shell.sh_substring_from_string("abcdef", 2, 4)

    # Terminate a specified Android package (com.android.chrome) using multiple methods,
    # as there is no one-fits-all command.
    blocking_shell.kill_package("com.android.chrome")

    # After calling `kill_package`, the following commands are executed one after another to forcefully stop the package:
    stdout, stderr = blocking_shell.sh_force_stop(
        package, **kwargs
    )  # Use the `am force-stop` command.
    stdout, stderr = blocking_shell.sh_kill(
        package, **kwargs
    )  # Use the `kill` command.
    stdout, stderr = blocking_shell.sh_killall9(
        package, **kwargs
    )  # Use the `killall -9` command.
    stdout, stderr = blocking_shell.sh_am_kill(
        package, **kwargs
    )  # Use the `am kill` command.
    stdout, stderr = blocking_shell.sh_pkill(
        package, **kwargs
    )  # Use the `pkill` command.

    # Concatenate the contents of a file (/sdcard/window_dump.xml) without newlines.
    blocking_shell.sh_cat_file_join_newlines("/sdcard/window_dump.xml")

    # Check for open ports on the device.
    blocking_shell.sh_check_open_ports()

    # Clear data and cache for a specified Android package (com.android.chrome).
    blocking_shell.sh_clear_package("com.android.chrome")
    # Output: [[b'Success\r\n'], []]

    # Compare two files (/sdcard/window_dump.xml and /sdcard/window_dump2.xml).
    blocking_shell.sh_compare_2_files(
        "/sdcard/window_dump.xml", "/sdcard/window_dump2.xml"
    )

    # Start a new instance of logcat and capture the output in `stdout` while suppressing `stderr`.
    newinstance, stdout, stderr = blocking_shell.start_logcat(
        print_stdout=True, print_stderr=False
    )

    # Create a fast backup of a SQLite database in the same folder - /sdcard/your_sqlite.db.bak
    blocking_shell.sh_create_bak_of_file("/sdcard/your_sqlite.db")

    # Delete the content of a file, but not the file itself:
    # Create a file first using uiautomator
    blocking_shell.execute_sh_command("uiautomator dump")
    # Output: [[b'UI hierarchy dumped to: /sdcard/window_dump.xml\r\n'], []]
    blocking_shell.sh_empty_file("/sdcard/window_dump.xml")
    # Output: [[], []]
    blocking_shell.sh_cat_file("/sdcard/window_dump.xml")
    # Output: b''

    # Capture a raw screen image
    raw_screen_data = blocking_shell.sh_screencap()

    # To convert the data to a numpy array and save as a PNG:
    # cv2.imwrite('c:\\TESTADBRAWSCREENSHOT.PNG', np.frombuffer(raw_screen_data, dtype=np.uint8)[16:].reshape((900, 1600, 4))[...,[2,1,0]])

    # Capture a PNG screen image
    png_screen_data = blocking_shell.sh_screencap_png()

    # To convert the data to a numpy array:
    # cv2.imdecode(np.frombuffer(png_screen_data, np.uint8), cv2.IMREAD_COLOR)

    # Capture the UI hierarchy using uiautomator dump
    blocking_shell.execute_sh_command("uiautomator dump")

    # Use 'grep' to search for lines matching the specified pattern in a file
    blocking_shell.sh_grep(
        r"bounds=......",
        "/sdcard/window_dump.xml",
        escape=True,
        quote=False,
        extended_regexp=True,
        ignore_case=True,
        recursively=False,
        line_number=True,
        invert_match=False,
        files_with_matches=False,
        count=False,
    )

    blocking_shell.sh_netstat()

    # Remove Dalvik cache, data cache, and user cache using 'su' command
    blocking_shell.sh_remove_dalvik_cache()
    blocking_shell.sh_remove_data_cache()
    blocking_shell.sh_remove_user_cache()

    # Remount the system as read-write or read-only
    # Note: Not working for the next command yet, since all commands are executed in a subshell.
    blocking_shell.sh_remount_all_rw()
    blocking_shell.sh_remount_all_ro()
    # If you know how to fix that, let me know. Use this for now: .
    blocking_shell.execute_sh_command(
        "su -c 'mount --all -o remount,rw -t vfat; echo \"bibi\" > /data/baba.txt'"
    )

    # Enable or disable screen compatibility mode for the specified app (com.spotify.music)
    blocking_shell.sh_screen_compat_on("com.spotify.music")
    blocking_shell.sh_screen_compat_off()

    # Rename a file from '/sdcard/window_dump.xml' to '/sdcard/window_dumpxx.xml'
    blocking_shell.sh_rename("/sdcard/window_dump.xml", "/sdcard/window_dumpxx.xml")

    # Check if the path '/sdcard/window_dumpxx.xml' is a file
    blocking_shell.sh_is_file("/sdcard/window_dumpxx.xml")
    # Output: True

    # Get the RGB value at a specific coordinate (200, 300) on the device
    rgb_value = blocking_shell.sh_get_rgb_value_at(200, 300)
    # Output: (35, 37, 39)

    # List all installed keyboards on the device
    keyboard_list = blocking_shell.get_all_keyboards()
    # Output: ['com.android.inputmethod.latin/.LatinIME', 'com.android.adbkeyboard/.AdbIME']

    # Get the tree view of the '/sdcard/' directory
    tree_view_sdcard = blocking_shell.sh_get_treeview_of_folder("/sdcard/")
    # Out[10]:
    # ['|-',
    #  '|-20231024',
    #  '|-AUTOMAT',
    #  '|---tmpaam24gbf',
    #  '|-Android',
    #  '|---data',
    #  '|-----com.android.camera2',
    #  '|-------cache',
    #  '|-------files',
    #  '|-----com.android.chrome',

    # Get the tree view of the '/data/data' directory with superuser privileges (for protected directories)
    tree_view_data_data = blocking_shell.sh_get_treeview_of_folder(
        "/data/data", su=True
    )

    # Get lines 0 to 3 from the '/etc/hosts' file with superuser privileges
    lines_0_to_3 = blocking_shell.sh_get_lines_from_to_in_file(
        0, 3, "/etc/hosts", su=True
    )
    # Out[13]:
    # [[b'127.0.0.1       localhost\r\n',
    #   b'::1             ip6-localhost\r\n',
    #   b'127.0.0.1       coinhive.com\r\n'],
    #  []]

    # Get a specific line (line 3) from the '/etc/hosts' file with superuser privileges
    specific_line = blocking_shell.sh_get_specific_line_from_a_file(
        3, "/etc/hosts", su=True
    )
    #     # [[b'127.0.0.1       coinhive.com\r\n'], []]

    # Remove a specific line (line 0) from the '/sdcard/window_dump.xml' file
    blocking_shell.sh_remove_specific_line_from_a_file(0, "/sdcard/window_dump.xml")

    # Check the contents of the '/sdcard/window_dump.xml' file after removing a specific line
    file_contents = blocking_shell.sh_cat_file("/sdcard/window_dump.xml")
    # Out[22]: b''

    # Count the network connections and display the status of each connection
    network_connections = blocking_shell.sh_count_network_connections()
    # Out[23]:
    # [[b'      6 CLOSE_WAIT\r\n',
    #   b'      7 ESTABLISHED\r\n',
    #   b'      2 LISTEN\r\n',
    #   b'      1 TIME_WAIT\r\n'],
    #  []]

    # Get the chmod permissions of files in the '/sdcard/' directory
    chmod_permissions_sdcard = blocking_shell.sh_get_all_chmod_from_files_in_folder(
        "/sdcard/"
    )
    # Out[24]:
    # [[b'-rw-rw---- 660 /sdcard/ \r\n',
    #   b'-rw-rw---- 660 /sdcard/(rev)\r\n',
    #   b'-rw-rw---- 660 /sdcard/(tr\r\n',
    #   b'-rw-rw---- 660 /sdcard/-1_threads.notifications.db_text.txt\r\n',
    #   b'-rw-rw---- 660 /sdcard/1753_mem_12c00000.bin\r\n',
    #   b'-rw-rw---- 660 /sdcard/1753_mem_74d74000.bin\r\n',
    #   b'-rw-rw---- 660 /sdcard/1753_mem_74ecd000.bin\r\n',
    #   b'-rw-rw---- 660 /sdcard/1753_mem_77d75000.bin\r\n',
    #   b'-rw-rw---- 660 /sdcard/1753_mem_ce771000.bin\r\n',

    # List all connected IP addresses
    connected_ips = blocking_shell.sh_list_all_connected_ips()
    # Out[25]:
    # [[b'\r\n',
    #   b'128.116.127.8\r\n',
    #   b'128.116.45.3\r\n',
    #   b'23.61.138.153\r\n',
    #   b'5.226.179.25\r\n'],
    #  []]
    # Get BIOS information (root only)
    bios_info = blocking_shell.sh_get_bios_info()
    # [[b'RSD PTR \r\n',
    #   b'innotek GmbH\r\n',
    #   b'VirtualBox\r\n',
    #   b'12/01/2006\r\n',
    #   b'innotek GmbH\r\n',
    #   b'VirtualBox\r\n',
    #   b'Virtual Machine\r\n',
    #   b'Oracle Corporation\r\n',

    # Display a hex dump of the specified file
    hex_dump = blocking_shell.sh_hexdump("/sdcard/window_dumpxx.xml")
    # Out[29]:
    # [[b"0000000   <   ?   x   m   l       v   e   r   s   i   o   n   =   '   1\r\n",
    #   b"0000010   .   0   '       e   n   c   o   d   i   n   g   =   '   U   T\r\n",
    #   b"0000020   F   -   8   '       s   t   a   n   d   a   l   o   n   e   =\r\n",
    #   b"0000030   '   y   e   s   '       ?   >   <   h   i   e   r   a   r   c\r\n",

    # Count the number of lines in the '/etc/hosts' file (root only)
    line_count = blocking_shell.sh_count_lines_in_file("/etc/hosts", su=True)
    # Out[31]: [3, b'/etc/hosts']

    # Get kernel information (root only)
    kernel_info = blocking_shell.sh_get_kernel_infos()

    # Get the IP address from the hostname 'google.com'
    ip_address = blocking_shell.sh_get_ip_from_host("google.com")
    # Out[34]: '142.251.128.14'

    # Get the newest file in the '/sdcard/' folder
    newest_file = blocking_shell.sh_newest_file_in_folder("/sdcard/")
    # Out[35]: [[b'/sdcard/dumpdata.tmp\r\n'], []]

    # Print the '/etc/hosts' file with line numbers (root only)
    hosts_file_lines = blocking_shell.sh_print_file_with_linenumbers(
        "/etc/hosts", su=True
    )
    # Out[3]:
    # [[b'1:127.0.0.1       localhost\r\n',
    #   b'2:::1             ip6-localhost\r\n',
    #   b'3:127.0.0.1       coinhive.com\r\n'],
    #  []]

    # Display a detailed process overview
    process_overview = blocking_shell.sh_ps_a_t_l_z()

    # Get details of a process with PID 1737
    details_of_pid_1737 = blocking_shell.sh_get_details_from_pid(1737)
    # [[b'COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME\r\n',
    #   b'logd       1737       logd  cwd       DIR                0,2      1000          2 /\r\n',
    #   b'logd       1737       logd  rtd       DIR                0,2      1000          2 /\r\n',
    #   b'logd       1737       logd  txt       REG                8,1    186648     265642 /system/bin/logd\r\n',
    #   b'logd       1737       logd  mem       REG                8,1    186648     265642 /system/bin/logd\r\n',
    #   b'logd       1737       logd  mem       REG                8,1     15056     264521 /system/lib64/libnetd_client.so\r\n',
    #   b'logd       1737       logd  mem       REG                8,1     23448     263965 /system/lib64/libcap.so\r\n',
    #   b'logd       1737       logd  mem       REG                8,1     73472     264133 /system/lib64/libbase.so\r\n',
    #   b'logd       1737       logd  mem       REG                8,1     43928     264178 /system/lib64/libsysutils.so\r\n',

    # Show network connections in a detailed format
    netstat_details = blocking_shell.sh_netstat_tlnp()
    # [[b'tcp',
    #   b'29289',
    #   b'0',
    #   b'10.0.2.15:42398',
    #   b'5.226.179.25:443',
    #   b'CLOSE_WAIT',
    #   b'-'],

    # Dump detailed process information with 'lsof' command (root only)
    detailed_process_info = blocking_shell.sh_get_details_with_lsof(su=True)
    blocking_shell.sh_get_details_with_lsof(su=True)
    # [[b'COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME\r\n',
    #   b'init          1       root  cwd       DIR                0,2      1000          2 /\r\n',
    #   b'init          1       root  rtd       DIR                0,2      1000          2 /\r\n',
    #   b'init          1       root  txt       REG                0,2   2409528       7182 /init\r\n',
    #   b'init          1       root  mem       REG                0,2   2409528       7182 /init\r\n',
    #   b'init          1       root  mem       REG               0,16    131072       8407 /dev/__properties__/properties_serial\r\n',

    # Display detailed network output, including IP addresses
    network_ip_info = blocking_shell.sh_show_ips()

    # Terminate a process that is locking a file at a specified path (root only)
    blocking_shell.sh_kill_process_that_is_locking_a_file("...some path", su=True)

    # Print lines of the '/etc/hosts' file that have at least 26 characters
    long_lines_in_hosts_file = (
        blocking_shell.sh_print_lines_of_file_with_at_least_length_n(
            "/etc/hosts", 26, su=True
        )
    )
    # Out[16]:
    # [[b'::1             ip6-localhost\r\n', b'127.0.0.1       coinhive.com\r\n'],
    #  []]

    # Show folders in the PATH environment variable (non-root)
    folders_in_path = blocking_shell.sh_show_folders_in_PATH(su=False)
    # Out[18]:
    # [[b'/sbin\r\n',
    #   b'/system/sbin\r\n',
    #   b'/system/bin\r\n',
    #   b'/system/xbin\r\n',
    #   b'/odm/bin\r\n',
    #   b'/vendor/bin\r\n',
    #   b'/vendor/xbin\r\n'],
    #  []]

    # Dry run of removing files matching the pattern '/sdcard/Download/*' (root only)
    # This command shows the files that would be removed without actually deleting them.
    dry_run_remove_files = blocking_shell.sh_rm_dry_run("/sdcard/Download/*")
    # Out[21]:
    # [[b'rm /sdcard/Download/Nearby Share /sdcard/Download/ba.html /sdcard/Download/baba.png /sdcard/Download/babaxx2.mhtml /sdcard/Download/bibi.png /sdcard/Download/bibixx.png /sdcard/Download/datetmp.log /sdcard/Download/tmp5j75s57u.tar\r\n'],
    #  []]

    # List IPv4 network interfaces and their associated IP addresses
    ipv4_interfaces = blocking_shell.sh_ipv4_interfaces()
    # Out[22]: [[b'lo 127.0.0.1\r\n', b'eth0 10.0.2.15\r\n'], []]

    # List processes and their CPU usage
    processes_cpu_usage = blocking_shell.sh_list_procs_cpu_usage()
    # Out[23]:
    # [[b'UID            PID  PPID C STIME TTY          TIME CMD\r\n',
    #   b'u0_a60       10218  1790 10 12:53:42 ?    00:19:24 com.roblox.client\r\n',
    #   b'u0_i2         8596  2178 3 11:30:32 ?     00:07:34 com.android.chrome:sandboxed_process0\r\n',
    #   b'u0_a31        8628  1791 2 11:30:33 ?     00:04:49 com.android.chrome:privileged_process0\r\n',
    #   b'system        1811     1 1 10:10:57 ?     00:01:59 surfaceflinger\r\n',
    #   b'system        1958  1790 0 10:10:58 ?     00:00:57 system_server\r\n',
    #   b'audioserver   1805     1 0 10:10:57 ?     00:00:31 audioserver\r\n',

    # List currently running processes
    running_processes = blocking_shell.sh_list_current_running_procs()
    # Out[24]:
    # [[b' 0.0     1 init\r\n',
    #   b' 0.0     2 [kthreadd]\r\n',
    #   b' 0.0     3 [rcu_gp]\r\n',
    #   b' 0.0     4 [rcu_par_gp]\r\n',
    #   b' 0.0     6 [kworker/0:0H-kblockd]\r\n',

    blocking_shell.sh_get_interfaces_and_mac()
    # Out[25]:
    # [['dummy0', 'ae:9c:a5:bd:92:cf'],
    #  ['eth0', '08:00:27:0e:38:b3'],
    #  ['ip6tnl0', '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00'],

    # List files in the '/sdcard/Download' directory, sorted by newest first
    # The output includes details like permissions, owner, size, date, and file name.
    newest_files = blocking_shell.sh_list_files_newest_first("/sdcard/Download")
    # Out[26]:
    # [['-rw-rw----',
    #   '1',
    #   'root',
    #   'sdcard_rw',
    #   '10240',
    #   '2023-10-29',
    #   '20:48 tmp5j75s57u.tar'],
    #  ['-rw-rw----',
    #   '1',
    #   'root',
    #   'sdcard_rw',
    #   '294188',
    #   '2023-10-25',
    #   '18:06 baba.png'],

    # Get the number of CPUs on the device
    number_of_cpus = blocking_shell.sh_number_of_cpus()
    # Out[28]: 4

    # Get the internal IP addresses of the device (loopback and local network)
    internal_ip_addresses = blocking_shell.sh_get_internal_ip_addr()
    # Out[29]: ['127.0.0.1', '10.0.2.15']

    # Get the external IP address of the device (requires an internet connection)
    external_ip_address = blocking_shell.sh_get_external_ip()
    # Out[30]: '189.XXXXXXX'

    # Get the MAC addresses of all network interfaces on the device
    mac_addresses = blocking_shell.sh_get_all_mac_addresses()
    # Out[31]: ['ae:9c:a5:bd:92:cf', '08:00:27:0e:38:b3']

    # Get the number of active TCP connections on the device
    number_of_tcp_connections = blocking_shell.sh_number_of_tcp_connections()

    # Dump all files with a '.db' extension on the entire system
    db_files_list = blocking_shell.sh_dump_all_db_files(as_pandas=False)

    # Dump all databases in the 'data/data' directory (not limited to '.db' files)
    databases_in_data_data = blocking_shell.sh_dump_all_databases_in_data_data(
        as_pandas=False
    )

    # Count the number of files in the '/sdcard' directory
    number_of_files_in_sdcard = blocking_shell.sh_count_files_in_folder("/sdcard")
    # Out[33]: 826

    # List input devices, including details like device names and supported events
    input_devices = blocking_shell.sh_list_input_devices()
    # Out[34]:
    # [[b'add device 1: /dev/input/event6\r\n',
    #   b'  name:     "Android Power Button"\r\n',
    #   b'  events:\r\n',
    #   b'    KEY (0001): KEY_POWER             KEY_WAKEUP           \r\n',
    #   b'  input props:\r\n',
    #   b'    <none>\r\n', ......

    # Get the input devices that are candidates for sending touch events using sendevent
    sendevent_input_devices = blocking_shell.sh_get_sendevent_input_devices()
    # Out[35]: [['/dev/input/event4', '32767'], ['/dev/input/event5', '65535']]

    # Use the previously obtained data to execute a touch event using sendevent
    blocking_shell.sh_sendevent_touch(
        x=600,  # X coordinate
        y=400,  # Y coordinate
        inputdev="event4",  # Input device (without '/dev/input/')
        inputdevmax=32767,  # Maximum value from sh_get_sendevent_input_devices()
        width=1600,  # Screen width
        height=900,  # Screen height
    )

    # On a Windows system, open a new cmd.exe window to record getevent data
    # This is necessary to capture events, and the data will be saved to the 'myeventfile' file
    blocking_shell.sh_record_getevent(tmpfilegetevent="myeventfile")

    # View the contents of the recorded event data file located at '/sdcard/myeventfile'
    captured_event_data = blocking_shell.sh_cat_file("/sdcard/myeventfile")

    # Record getevent data as binary from the specified device, e.g., '/dev/input/event4', and save it to 'somefilename'
    outputpath = blocking_shell.sh_record_getevent_as_binary_data(
        device="/dev/input/event4", tmpfilegetevent="somefilename"
    )

    # Pause execution until the user presses Enter to continue
    input("Press enter when ready")

    # Convert the binary getevent data into decimal values
    # 'purebindata' can be sent to the device to execute the commands (e.g., using https://github.com/hansalemaos/geteventplayback)
    purebindata, alldata = blocking_shell.convert_getevent_binary_data_to_decimal(
        outputpath
    )

    fi = blocking_shell.sh_record_getevent(tmpfilegetevent="getevenfile2")
    # File will be saved: /sdcard/getevenfile2
    # fi
    # Out[5]: '/sdcard/getevenfile2'

    # Exit the 'su' shell (superuser mode), if it was previously entered
    blocking_shell.exit_from_su_shell()

    # Capture events from a specified input device, e.g., 'event4', with better timestamp formatting
    stdout, stderr = blocking_shell.sh_getevent_capture(
        "event3", 1000, disable_print_stdout=False
    )

    # The captured data includes event timestamps and coordinates (x, y)

    #   1698717226            0        54020            4            0
    #      3473411        23642        24106        25920            0   x= 1154
    #       316164            0            3           54        19633   y=  539
    #   1698717226            0        54020            4            0
    #       131072            0        24106        25920            0
    #       316164            0            0            0            0
    #   1698717226            0        55679            4            0
    #      3473411        23679        24106        25920            0   x= 1156
    #       317823            0            3           54        19568   y=  537
    #   1698717226            0        55679            4            0
    #       131072            0        24106        25920            0
    #       317823            0            0            0            0
    #   1698717226            0        56899            4            0
    #      3473411        23679        24106        25920            0   x= 1156
    #       319043            0            3           54        19568   y=  537
    #   1698717226            0        56899            4            0
    #       131072            0        24106        25920            0
    #       319043            0            0            0            0
    #   1698717226            0        23086            5            0

    # On Windows, open a new cmd.exe shell in a separate window
    blocking_shell.open_adb_shell()
    version = blocking_shell.sh_get_android_version()
    blocking_shell.get_all_devices()

    print(version)

    blocking_shell.execute_adb_command(
        f"-s {blocking_shell.device_serial} reverse tcp:1300 tcp:1600"
    )

    # muuuuch faster than adb pull / adb shell cat
    # Requirements: Windows / Cygwin (with nc.exe and tar.exe)
    # busybox on the Android device and su
    blocking_shell.netcatcopy(
        tarpath="tar.exe",
        netcatpath="nc.exe",
        outputfolder="c:\\testbackuo3",  # will be created
        foldertodownload="/data/data/com.instagram.lite/",
        tmpfilename="taradbdownload.tar",
    )

    # Some non shell ADB commands
    blocking_shell.adb_reconnect()
    blocking_shell.adb_root()
    blocking_shell.adb_remount_as_rw()

    blocking_shell.adb_install(
        path=r"C:\Users\hansc\Downloads\Opera Mini_ Fast Web Browser_72.0.2254.67482_Apkpure.apk",
        grand_permissions=True,
        replace=True,
        allow_test=True,
        allow_downgrade=False,
        to_83=True,
    )
    packname = [
        x.strip().split(b":")[-1].decode("utf-8")
        for x in blocking_shell.sh_pm_list_packages_3()[0]
        if b"opera" in x
    ][0]
    blocking_shell.adb_uninstall(packname)
    blocking_shell.adb_unroot()

    # port forwarding
    blocking_shell.adb_forward_port(6000, 6100)
    blocking_shell.adb_reverse_port(9000, 9100)
    p1 = blocking_shell.adb_show_forwarded_ports()
    p2 = blocking_shell.adb_show_reversed_ports()
    print(p1)
    print(p2)
    blocking_shell.adb_remove_forwarded_port(6000)
    blocking_shell.adb_remove_reversed_port(9000)
    p1 = blocking_shell.adb_show_forwarded_ports()
    p2 = blocking_shell.adb_show_reversed_ports()
    print(p1)
    print(p2)
    # [[b'127.0.0.1:5555 tcp:6000 tcp:6100', b''], []]
    # [[b'host-9 tcp:9000 tcp:9100', b''], []]
    # [[b''], []]
    # [[b''], []]
    s01, s02 = blocking_shell.adb_pull(
        path_device="/sdcard/window_dump.xml",
        path_pc="C:\\PUSHEDTEST",
        escape_path=True,
    )
    s03, s04 = blocking_shell.adb_push(
        path_pc=r"C:\Users\hansc\Downloads\1633637532_Royale High Candy Autofarm .webp",
        path_device="/sdcard/Download",
        escape_path=True,
        to_83=False,
    )
    blocking_shell.sh_get_file_extension("/sdcard/window_dump.xml")
    #  'xml'
    blocking_shell.sh_get_md5sum(path="/sdcard/window_dump.xml")
    # '027001170290b3415144019a4c3db567'
    blocking_shell.sh_realpath(path="/sdcard/window_dump.xml")
    # '/storage/emulated/0/window_dump.xml'
    blocking_shell.sh_dirname(path="/sdcard/window_dump.xml")
    blocking_shell.execute_sh_command("uiautomator dump")
    blocking_shell.sh_rename_file_to_md5("/sdcard/window_dump.xml")
    #  '/sdcard/09e1ad07ae0c4f3df822e18977c2fd3f.xml'
    blocking_shell.sh_get_size_of_terminal()
    # : [80, 24]
    blocking_shell.sh_change_to_dir("/sdcard/Download")
    print(blocking_shell.sh_ls())
    blocking_shell.sh_change_to_prev_working_dir()
    print(blocking_shell.sh_ls())

    blocking_shell.sh_create_file_with_content("bibi baba", "/sdcard/çç ççtest.txt")
    # Out[7]: [[], []]
    blocking_shell.sh_cat_file("/sdcard/çç ççtest.txt")
    # Out[8]: b'bibi baba'
    # with binary data:
    blocking_shell.sh_create_file_with_content(b"bibi baba", "/sdcard/çç ççötest.txt")
    # Out[9]: [[], []]
    blocking_shell.sh_cat_file("/sdcard/çç ççötest.txt")
    # Out[10]: b'bibi baba'

    blocking_shell.sh_ping_one_time("www.google.com")
    # Out[3]:
    # [[b'PING www.google.com (142.250.218.68) 56(84) bytes of data.\r\n',
    #   b'\r\n',
    #   b'--- www.google.com ping statistics ---\r\n',
    #   b'1 packets transmitted, 1 received, 0% packet loss, time 0ms\r\n',
    #   b'rtt min/avg/max/mdev = 16.937/16.937/16.937/0.000 ms\r\n'],
    #  []]
    blocking_shell.sh_create_file_with_content(
        b"   bibi\n    baba\n ddd", "/sdcard/çç ççötest.txt"
    )

    fiu = blocking_shell.sh_cat_file_without_leading_whitespaces(
        "/sdcard/çç ççötest.txt"
    )

    # This does only work wit blocking_shell, the subshells can't set vars
    print(fiu)
    sh_variable_existsv = blocking_shell.sh_variable_exists("bibi", global_cmd=True)
    print(sh_variable_existsv)
    blocking_shell.execute_sh_command_global("bibi=5")
    sh_variable_existsv2 = blocking_shell.sh_variable_exists("bibi", global_cmd=True)
    print(sh_variable_existsv2)

    # Another way to call the blocking_shell
    blocking_shell.execute_sh_command_global("ls")

    blocking_shell.sh_get_file_with_tstamp("testfile", ".tar.gz")
    blocking_shell.sh_memory_dump()
    blocking_shell.sh_ls_fp("/sdcard/")
    blocking_shell.sh_iptables()
    blocking_shell.sh_reverse_file("/sdcard/your_sqlite_text.txt")

    blocking_shell.sh_append_to_file(
        filedata="bbabab babab", path="/sdcard/çç ççötest.txt"
    )
    blocking_shell.sh_echo_rev("My name is John")
    blocking_shell.sh_netstat_ip_group()
    # Out[3]:
    # [[b'      1 142.251.128.106\n',
    #   b'      1 142.251.128.42\n',
    #   b'      1 142.251.129.202\n',
    #   b'      3 142.251.128.10\n'],
    #  []]
    blocking_shell.sh_process_tree()
    # [[b'init(1)-+-Binder:1755_2(1755)-+-sdcard(2143)-+-{sdcard}(2148)\n',
    #   b'        |                     |              |-{sdcard}(2149)\n',
    #   b'        |                     |              `-{sdcard}(2150)\n',
    #   b'        |                     |-{Binder:1755_1}(1757)\n',
    #   b'        |                     |-{Binder:1755_2}(1758)\n',
    #   b'        |                     |-{Binder:1755_3}(1759)\n',
    #   b'        |                     `-{Binder:1755_4}(1790)\n',
    #   b'        |-Binder:1792_2(1792)-+-ip6tables-resto(1848)\n',
    blocking_shell.sh_list_hdds()
    blocking_shell.sh_cat_file_without_leading_whitespaces("/sdcard/çç ççötest.txt")
    blocking_shell.sh_list_hdds_real()
    blocking_shell.sh_lsof_filehandles()
    blocking_shell.sh_list_exe_in_path()
    blocking_shell.sh_free_memory()
    blocking_shell.sh_ls_size("/sdcard/Download")
    # Out[3]:
    # [[b'-rw-rw---- 1 root sdcard_rw       0 2023-10-21 20:31 ba.html\n',
    #   b'total 6444\n',
    #   b'-rw-rw---- 1 root sdcard_rw      21 2023-10-24 22:48 datetmp.log\n',
    #   b'-rw-rw---- 1 root sdcard_rw      46 2023-10-25 17:57 bibixx.png\n',
    #   b'-rw-rw---- 1 root sdcard_rw    5696 2023-10-25 18:06 bibi.png\n',
    #   b'-rw-rw---- 1 root sdcard_rw   10240 2023-10-29 20:48 tmp5j75s57u.tar\n',
    #   b'-rw-rw---- 1 root sdcard_rw   28682 2023-11-01 19:34 1633637532_Royale High Candy Autofarm .webp\n',
    #   b'-rw-rw---- 1 root sdcard_rw   92590 2023-10-31 12:42 asgasdfasdfasdf.png\n',
    #   b'-rw-rw---- 1 root sdcard_rw  294188 2023-10-25 18:06 baba.png\n',
    #   b'-rw-rw---- 1 root sdcard_rw 6147735 2023-10-25 18:06 babaxx2.mhtml\n']
    # The day your device came alive
    blocking_shell.sh_get_install_date()
    blocking_shell.sh_get_audio_playing_procs()
    blocking_shell.sh_get_kernel_infos()
    blocking_shell.sh_get_procs_with_open_connections()
    blocking_shell.sh_chr("77")
    blocking_shell.sh_list_extensions_in_folder("/sdcard/Download")
    # Out[3]:
    # [[b'      1 html\n',
    #   b'      1 log\n',
    #   b'      1 mhtml\n',
    #   b'      1 tar\n',
    #   b'      1 webp\n',
    #   b'      4 png\n'],
    blocking_shell.sh_comment_out_line_in_file(2, "/sdcard/your_sqlite_text.txt")
    blocking_shell.sh_cat_file("/sdcard/your_sqlite_text.txt")
    blocking_shell.sh_tar_backup_of_folder_to_sdcard("/sdcard/Download")
    # b'#!/bin/bash\nexec 2>/sdcard/errortmp16989042186992085.txt\nexec 1>/sdcard/outputtmp16989042186992085.txt\ncd /sdcard/Download\nfind . -type f -exec md5sum {} \\;\nexec 1>&-\nexec 2>&-\n\necho -n -e xxxCOMMANDxxxDONExxx>> /sdcard/outputtmp16989042186992085.txt\necho -n -e xxxCOMMANDxxxDONExxx >> /sdcard/errortmp16989042186992085.txt\n'
    # Out[3]:
    # [[b'bdb92ce5db632c499f8c1d52b6bcff13  ./babaxx2.mhtml\n',
    #   b'6f44a9d7667d8e166cb5d5cbbb674709  ./bibi.png\n',
    #   b'd41d8cd98f00b204e9800998ecf8427e  ./ba.html\n',
    blocking_shell.sh_delete_all_files_in_folder_except_newest("/sdcard/Download9")
    blocking_shell.sh_apps_using_internet()
    blocking_shell.sh_goto_next_sibling_folder()
    blocking_shell.sh_cd_and_search_string_in_files("/sdcard/Download", "html")

    # This method has to be executed with blocking_subshell - base64 - due to some chars in the script
    coords = blocking_subshell.sh_search_for_colors(
        colorlist=[(183, 28, 28)], global_cmd=False
    )
    size = blocking_shell.sh_calculate_size_of_folders("/sdcard/")
    # [(4, b'20231024/'), (8, b'AUTOMAT/'), (1045336, b'Android/'), (344, b'DCIM/'), (6460, b'Download/'), (100, b'Download2/'), (8, b'Download4/'), (96, b'Download9/'), (4, b'REPLACE_BINFOLDER/'), (16, b'a/'),
    blocking_shell.sh_disable_input_device("/dev/input/event5")

    blocking_shell.sh_list_dev_input()
    for d in blocking_shell.sh_list_dev_input():
        blocking_shell.sh_disable_input_device(d, su=True)

    # self.execute_sh_command('getprop ro.secure ; /boot/android/android/system/xbin/bstk/su',su=True)
    # self.execute_sh_command('getprop')

    # self.execute_sh_command('setprop gsm.sim.operator.alpha O2')
    # Out[8]: [[], []]
    # self.execute_sh_command('getprop')
    # self.execute_sh_command('getprop')
    blocking_shell.sh_get_all_props()

    # everything that can be passed to dumpsys
    blocking_shell.sh_get_all_dumpsys_services()
    # ['DockObserver',
    #  'RTVboxMM',
    #  'SurfaceFlinger',
    #  'accessibility',
    #  'account',
    #  'activity',
    #  'alarm',
    #  'android.security.keystore',
    #  'android.service.gatekeeper.IGateKeeperService',
    #  'appops',
    #  'appwidget',
    #  'audio',
    #  'autofill',
    #  'backup',
    #  'battery',

    # separated in a list of lists
    blocking_shell.sh_dumpsys_everything()
    # checks if the activity accepts the parameter -h
    blocking_shell.sh_get_all_extra_options_from_dumpsys()
    # self.sh_get_all_extra_options_from_dumpsys()
    # Out[5]:
    # [['activity',
    #   [[b'Total number of currently running services:0\n',
    #     b'Activity manager dump options:\n',
    #     b'  [-a] [-c] [-p PACKAGE] [-h] [WHAT] ...\n',
    #     b'  WHAT may be one of:\n',
    #     b'    a[ctivities]: activity stack state\n',
    #     b'    r[recents]: recent activities state\n',
    #     b'    b[roadcasts] [PACKAGE_NAME] [history [-s]]:

    # Helps to avoid ERROR: could not get idle state
    blocking_shell.sh_nice(
        cmd="uiautomator dump",
        value=-19,
    )
    # implemented here and fast lxml parsing:
    df1 = blocking_shell.uiautomator_nice20(
        timeout=60, nice=True, su=True, as_pandas=True
    )
    #       tag index text  ... height      ratio  NAF
    # 2    node     0       ...    900   1.777778  NaN
    # 3    node     0       ...    900   1.777778  NaN
    # 4    node     0       ...    864   1.851852  NaN
    # 5    node     0       ...    864   1.851852  NaN
    # 6    node     0       ...    864   1.851852  NaN
    # ..    ...   ...  ...  ...    ...        ...  ...
    # 667  node     1       ...     72        1.0  NaN
    # 668  node     5       ...     84   0.857143  NaN
    # 669  node     6       ...     84   0.857143  NaN
    # 670  node     0       ...     84   0.857143  NaN
    # 671  node     1       ...     36  44.444444  NaN
    # [670 rows x 32 columns]

    df2 = blocking_shell.get_all_activity_elements(as_pandas=True)
    # Out[9]:
    #       START_X  START_Y  CENTER_X  ...  VIEW_INDEX  HIERACHY_CLUSTER  HIERACHY_SINGLE
    # 0           0        0       800  ...           0                 1                0
    # 1           0        0       800  ...           0                 1                1
    # 2           0        0       800  ...           0                 1                2
    # 3           0        0       800  ...           0                 1                3
    # 4         714      333       799  ...           0                 1                4
    #        ...      ...       ...  ...         ...               ...              ...
    # 1297        0       36         0  ...           3                57                3
    # 1298        0        0       800  ...           3                58                0
    # 1299        0        0         0  ...           3                58                1
    # 1300        0        0       800  ...           3                59                0
    # 1301        0        0       800  ...           3                60                0
    # [1302 rows x 40 columns]

    blocking_subshell.sh_grep_proc_top("chrome", su=True)
    blocking_shell.sh_force_idle()
    blocking_subshell.sh_unforce_idle()
    blocking_subshell.sh_get_current_focus()
    blocking_subshell.sh_get_all_possible_activities()
    # Out[6]:
    # {'Activity Resolver Table:': {'Full MIME Types:': {'application/com.google.android.gms.car:': {'53d74a6 com.google.android.gms/.car.FirstActivity filter e95d41': {'Action: "android.nfc.action.NDEF_DISCOVERED"': 6,
    #      'Category: "android.intent.category.DEFAULT"': 7,
    #      'Type: "application/com.google.android.gms.car"': 8}},
    #    'application/pkix-cert:': {'3196ee7 com.android.certinstaller/.CertInstallerMain filter acffff8': {'Action: "android.intent.action.VIEW"': 11,
    #      'Category: "android.intent.category.DEFAULT"': 12,
    #      'Type: "application/x-x509-ca-cert"': 13,
    #      'Type: "application/x-x509-user-cert"': 14,
    #      'Type: "application/x-x509-server-cert"': 15,
    #      'Type: "application/x-pkcs12"': 16,
    #      'Type: "application/application/x-pem-file"': 17,
    #      'Type: "application/pkix-cert"': 18,

    blocking_subshell.sh_am_i_su()
    # Out[7]: True
    blocking_subshell.sh_get_newest_file_in_folder_as_tar(
        folder="/sdcard/Download/", file_filter="*", tarpath="/sdcard/newestar.tar.gz"
    )
    # Out[9]: [[b'./bet365 - Apostas Desportivas Online (3).mhtml\r\n'], []]
    blocking_subshell.sh_delete_files_in_folder_older_than(
        "/sdcard/Download/", "*.mhtml", "+1"
    )

    alla = blocking_subshell.get_all_activity_elements(
        as_pandas=False,
    )
    alla = blocking_subshell.sh_get_all_possible_activities()
    blocking_subshell.sh_copy_dir_recursive("/sdcard/Download/", "/sdcard/Download3")
    blocking_subshell.sh_remove_folder("/sdcard/Download3")
    coli = blocking_subshell.sh_number_of_lines_words_chars_in_file(
        file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    print(coli)
    blocking_subshell.sh_tail_bytes(
        n=10, file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_tail_lines(
        n=10, file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_head_bytes(
        n=10, file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_head_lines(
        n=10, file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_sort_file_reverse(
        "/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_sort_file(
        "/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml"
    )
    blocking_subshell.sh_create_file_with_content("ls", "/sdcard/tttt.sh")
    blocking_subshell.sh_chmod_x("/sdcard/tttt.sh")
    blocking_subshell.sh_execute_sh_script("/sdcard/tttt.sh")
    blocking_subshell.sh_type("ls")
    # Out[4]: [[b'ls is a tracked alias for /system/bin/ls\n'], []]
    blocking_subshell.sh_which_a("ls")
    # Out[3]: [[b'/system/bin/ls\n', b'/system/xbin/ls\n', b'/vendor/bin/ls\n'], []]
    blocking_subshell.sh_create_symbolic_link(
        "/sdcard/tttt.sh", "/data/ttttex.sh"
    )  # not possible on sdcard
    blocking_subshell.sh_execute_sh_script("/data/ttttex.sh")
    blocking_subshell.sh_show_used_diskspace()
    blocking_subshell.sh_show_used_memory()
    blocking_subshell.sh_reboot()  # shutdown - emulator
    blocking_subshell.execute_sh_command("sleep 90 &")
    blocking_subshell.sh_jobs()
    blocking_subshell.sh_remount_all_rw()

    # Out[3]: [[4308, b'[1] + Running              \\sleep 90']]

    blocking_subshell.sh_disable_network_adapter("eth0")  # kicks adb connection
    blocking_subshell.sh_enable_network_adapter("eth0")
    blocking_subshell.sh_get_linux_version()
    blocking_subshell.sh_get_cpu_info()
    blocking_subshell.sh_get_mem_info()
    blocking_subshell.sh_whoami()
    blocking_subshell.sh_whoami(su=True)
    blocking_subshell.sh_id()
    blocking_subshell.sh_get_user_groups()
    blocking_subshell.sh_paste(
        file="/sdcard/Download/bet365 - Apostas Desportivas Online (96).mhtml",
        delimiter=" ",
    )

    # get sorted file list (by modification date)
    flist = blocking_subshell.sh_create_date_sorted_filelist(
        "/sdcard/Download", "/sdcard/htmlstuff.txt", "*.mhtml"
    )
    print(flist)
    self = eval_shell

    print(blocking_subshell.sh_test_directory("/sdcard/"))
    print(blocking_subshell.sh_test_exists_in_any_form("/sdcard/"))
    print(blocking_subshell.sh_test_executable("/sdcard/"))
    print(blocking_subshell.sh_test_regular_file("/sdcard/"))
    print(blocking_subshell.sh_test_readable("/sdcard/"))
    print(blocking_subshell.sh_test_named_pipe("/sdcard/"))
    print(blocking_subshell.sh_test_block_device("/sdcard/"))
    print(blocking_subshell.sh_test_character_device("/sdcard/"))
    print(blocking_subshell.sh_test_link("/sdcard/"))
    # True
    # True
    # True
    # False
    # True
    # False
    # False
    # False
    # False

    # High speed webscraping - bet365 Football
    htmlresults = eval_shell.sh_scrape_html(
        file_path="/sdcard/Download/bet365 - Apostas Desportivas Online.mhtml",
        mainblocks=[
            "Fixture_Container"
        ],  # parents blocks - regular expressions - need to be compatible with grep and re, which means that \s+, for example, is not allowed, and you have to use [0-9]+ instead of \d+
        subblocks=['ParticipantOddsOnly_Odds">', 'FixtureDetailsTwoWay_TeamName +">'],
    )  # child blocks - regular expressions - need to be compatible with grep and re, which means that \s+, for example, is not allowed , and you have to use [0-9]+ instead of \d+
    htmlresultswfilter = [
        k
        for k in [
            [
                y.split(">", maxsplit=1)[1].split("<", maxsplit=1)[0]
                for y in x
                if y.startswith("FixtureDetailsTwoWay_TeamName")
                or y.startswith("ParticipantOddsOnly_Odds")
            ]
            for x in htmlresults
        ]
        if k
    ]
    for x in htmlresultswfilter:
        print(x)

    # ['FC Astana', 'KF Ballkani', '2.25', '2.75', '3.75']
    # ['Al Khaleej Saihat', 'Al Taee', '2.37', '2.62', '3.75']
    # ['Al Raed', 'Al Shabab Riyadh', '1.80', '3.20', '4.75']
    # ['Al Hidd', 'Sitra', '5.00', '3.75', '1.61']
    # ['Al Shabab Manama', 'Al Hala', '2.05', '3.40', '3.40']
    # ['Chernomorets Balchik', 'CSKA Sofia', '41.00', '13.00', '1.04']
    # ["Stade d'Abidjan", 'CO Korhogo', '2.50', '2.40', '3.60']
    # ['NK Nafta 1903', 'ND Ilirija Ljubljana', '1.44', '4.33', '6.50']
    # ['Medeama SC', 'Nsoatreman FC', '2.20', '2.30', '5.00']
    # ['Venomous Vipers', 'Pac Academy', '2.30', '2.30', '4.50']
    # ['Naft Al-Wasat', 'Duhok', '2.15', '2.80', '3.50']
    # ['Rimini', 'Perugia', '4.00', '3.25', '1.90']
    # ['Al-Sailiya SC', 'Al-Shahaniya SC', '34.00', '19.00', '1.02']
    # ['Lusail', 'Al Mesaimeer SC', '17.00', '5.00', '1.18']
    # ['France (Musky) Esports', 'Portugal (Buconi) Esports', '1.083', '7.50', '19.00']
    # ['Germany (Nicolas_Rage) Esports', 'Argentina (Izzy) Esports', '1.30', '4.00', '10.00']
    # ['Man Utd (Adriano) Esports', 'Napoli (Iron) Esports', '1.20', '6.50', '8.50']
    # ['RB Leipzig (Rafaelo) Esports', 'A.Madrid (Bruno) Esports', '1.72', '4.33', '3.75']
    # ['Club Brugge (Danny) Esports', 'PAOK (Panic) Esports', '1.57', '4.50', '4.00']
    # ['Fenerbahce (Magdy) Esports', 'Fiorentina (aibothard) Esports', '3.00', '4.00', '1.90']

    # High speed webscraping - bet365 Tennis
    htmlresults = eval_shell.sh_scrape_html(
        file_path="/sdcard/Download/bet365 - Apostas Desportivas Online.mhtml",
        mainblocks=["Fixture_Container"],
        # parents blocks - regular expressions - need to be compatible with grep and re, which means that \s+, for example, is not allowed, and you have to use [0-9]+ instead of \d+
        subblocks=[
            'ParticipantOddsOnly_Odds">',
            "ovm-FixtureDetailsWithIndicators_PlayingIndicator",
        ],
    )  # child blocks - regular expressions - need to be compatible with grep and re, which means that \s+, for example, is not allowed , and you have to use [0-9]+ instead of \d+
    htmlresultswfilter = [
        k
        for k in [
            [
                y
                for y in x
                if "ovm-FixtureDetailsWithIndicators_PlayingIndicator" in y
                or y.startswith("ParticipantOddsOnly_Odds")
            ]
            for x in htmlresults
        ]
        if k
    ]
    for x in htmlresultswfilter:
        print("-----------------------------------")
        for y in x:
            if y.startswith("ovm-FixtureDetailsWithIndicators_PlayingIndicator"):
                try:
                    z = y.split("</div>")[1]
                    print(z)
                except Exception:
                    continue
            elif y.startswith("ParticipantOddsOnly_Odds"):
                try:
                    z = y.split(">")[1].split("<")[0]
                    print(z)
                except Exception:
                    continue

    # -----------------------------------
    # Leylah Fernandez
    # Magda Linette
    # 1.05
    # 11.00
    # -----------------------------------
    # Viktorija Golubic
    # Sofia Kenin
    # 1.95
    # 1.80
    # -----------------------------------
    # Fabio Fognini
    # Lorenzo Sonego
    # 1.12
    # 6.00
    # -----------------------------------
    # Marton Fucsovics
    # Pavel Kotov
    # 2.00
    # 1.80
    # -----------------------------------
    # Maria Lourdes Carle
    # Varvara Lepchenko
    # 1.14
    # 5.00
    # -----------------------------------
    # Braden Shick
    # Luciano Tacchi
    # 8.50
    # 1.05
    # -----------------------------------
    # Holden Koons
    # Dhakshineswar Suresh
    # 6.00
    # 1.11
    # -----------------------------------
    # Pedro Rodenas
    # Martin Borisiouk
    # 1.05
    # 8.50
    # -----------------------------------
    # Kennedy Shaffer
    # Stefani Webb
    # 1.75
    # 2.00
    # -----------------------------------
    # Raquel G Vilar
    # Gina Marie Dittmann
    # 17.00
    # 1.01
    # -----------------------------------
    # Saville/Tu
    # Seggerman/Trhac
    # 2.10
    # 1.66
    # -----------------------------------
    # Alves/Riberio
    # Carou/Ugo Carabelli
    # 3.00
    # 1.36
    # -----------------------------------
    # Karlovskiy/Serdarusic
    # Sandgren/Willis
    # 2.20
    # 1.61
    # -----------------------------------
    # Muhammad/Santamaria
    # Beck/Markham
    # 2.10
    # 1.66
    # -----------------------------------
    # Abduraimova/Monnet
    # Chang/Kozyreva
    # 2.50
    # 1.50
    # -----------------------------------
    # Cigarran/Hess
    # Rodriguez/Tenti
    # 26.00
    # 1.001
    # -----------------------------------
    # Urszula Radwanska
    # Kira Pavlova
    # 1.66
    # 2.10
    # -----------------------------------
    # Katherine Sebov
    # Dalayna Hewitt
    # 1.66
    # 2.10
    # -----------------------------------
    # Alexia Jacobs
    # Liv Hovde
    # 7.00
    # 1.083
    # ls -R / > /sdcard/lstest.txt -> execute that in another shell
    eval_shell.sh_wait_until_file_written_to_disk(
        file="/sdcard/lstest.txt", interval=0.1
    )
    eval_shell.sh_cat_file("/sdcard/lstest.txt")

    eval_shell.sh_is_valid_float(10.11)
    eval_shell.sh_is_valid_float("10.11.11")

    eval_shell.sh_is_valid_int(1011)
    eval_shell.sh_is_valid_int("10.11")
    eval_shell.sh_ls_human_readable("/sdcard/")

    eval_shell.sh_find_all_folder_full_path("/sdcard/")
    eval_shell.sh_check_environment_vars()
    # [[b'** PATH contains invalid directory /system/sbin\n',
    #   b'** PATH contains invalid directory /odm/bin\n',
    #   b'** PATH contains invalid directory /vendor/xbin\n',
    #   b'ERRORS:3\n'],
    eval_shell.sh_printenv()

    eval_shell.sh_freeze_proc("PID HERE")
    eval_shell.sh_unfreeze_proc("PID HERE")
    ############################################################################
    # to avoid UiAutomator crashes
    blocked = [
        eval_shell.sh_freeze_proc(int(x.strip().split()[1]))
        for x in eval_shell.sh_list_current_running_procs()[0]
        if b"com.kiwibrowser.browser:sandboxed_process" in x
    ]
    sleep(0.5)
    df = eval_shell.uiautomator_nice20(as_pandas=False)
    import pandas as pd

    df = pd.DataFrame(df).T
    unblocked = [
        eval_shell.sh_unfreeze_proc(int(x.strip().split()[1]))
        for x in eval_shell.sh_list_current_running_procs()[0]
        if b"com.kiwibrowser.browser:sandboxed_process" in x
    ]
    allg = []
    df2 = df.explode("all_parents")
    for name, group in df2.groupby("all_parents"):
        if not group.loc[group["class"] == "android.widget.TextView"].empty:
            if list(map(int, group["index"].to_list())) in [[0, 1, 2], [0]]:
                if len(group) == 3:
                    allg.append([True, group])
                else:
                    allg.append([False, group])

    from loophopper import FFIter

    l = FFIter(allg, ignore_exceptions=True, exception_replacement=None)
    for no in l:
        if no[0] is True:
            dfax = pd.concat([l.back(2)[1], l.back(1)[1], no[1]], ignore_index=True)
            print(dfax)
    ############################################################################
    # to avoid UiAutomator crashes
    blocked = [
        eval_shell.sh_freeze_proc(int(x.strip().split()[1]))
        for x in eval_shell.sh_list_current_running_procs()[0]
        if b"com.kiwibrowser.browser:sandboxed_process" in x
    ]
    sleep(0.5)
    df = eval_shell.uiautomator_nice20(as_pandas=False)
    import pandas as pd

    df = pd.DataFrame(df).T
    unblocked = [
        eval_shell.sh_unfreeze_proc(int(x.strip().split()[1]))
        for x in eval_shell.sh_list_current_running_procs()[0]
        if b"com.kiwibrowser.browser:sandboxed_process" in x
    ]
    allg = []
    df2 = df.explode("all_parents")
    for name, group in df2.groupby("all_parents"):
        # print(group)
        try:

            if list(map(int, group["index"].to_list()[:4])) in [[0, 1, 0, 1], [0, 0]]:
                if len(group) == 2:
                    if not group.loc[group.text.astype('string').str.contains(r'^\d+\.\d+$')].empty:
                        allg.append(group)
                if len(group) > 4:
                    g3 = group.loc[(group['index'] == '1') & (~group['text'].str.contains(r'^\d+$'))]
                    if len(g3) == 2:
                        allg.append(g3)
        except Exception:
            continue
    finalresus = [pd.concat(allg[x:x + 2], ignore_index=True) for x in range(0, len(allg), 2)]
    ############################################################################
    # Bounding boxes for elements on screen
    eval_shell.sh_show_fragments_on_screen()

    # Manage your settings
    # manager0
    # Out[5]:
    # {'secure': {'accessibility_captioning_enabled': {'value': '1',
    #    'get_value': (),
    #    'put_value': ()},
    #   'accessibility_display_inversion_enabled': {'value': 'null',
    #    'get_value': (),
    #    'put_value': ()},
    #   'accessibility_display_magnification_enabled': {'value': '0',
    #    'get_value': (),
    #    'put_value': ()},

    # manager0.secure.accessibility_display_magnification_scale.put_value(4.0)
    # Out[6]: ''
    # manager0.secure.accessibility_display_magnification_scale.get_value()
    # Out[7]: '4.0'
    manager0 = eval_shell.sh_get_settings_manager()

    # same thing for getprop
    manager1 = eval_shell.sh_get_getprop_setprop_manager()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

usefuladb-0.24.tar.gz (183.1 kB view hashes)

Uploaded Source

Built Distribution

usefuladb-0.24-py3-none-any.whl (132.8 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page