Esempio n. 1
0
def switch_to_tcpip(port: int = 5555):
    logger.info("Checking for connected devices")
    try:
        output = execute_adb(["wait-for-local-device"], timeout=1)
        logger.info("[ADB] %s", output)
        network_device = next(filter(lambda d: ":" in d.serial, adb.device_list()))
        if network_device is not None:
            logger.info("Found connected device: %s", network_device)
            return network_device
    except subprocess.TimeoutExpired:
        logger.warning("No networked device found.")
        pass

    logger.info("Switching to tcpip for USB connected device")
    logger.info("Waiting for device")
    output = execute_adb(["wait-for-usb-device"])
    logger.info("[ADB] %s", output)
    ip = adb.device().wlan_ip()
    logger.info(f"Trying to connect to {ip}:{port}")
    output = execute_adb(["-d", "tcpip", f"{port}"])
    logger.info("[ADB] %s", output)
    try:
        output = execute_adb(["disconnect", f"{ip}:{port}"])
    except subprocess.CalledProcessError as e:
        logger.warning("[ADB] %s", e)
    logger.info("[ADB] %s", output)
    output = adb.connect(f"{ip}:{port}")
    logger.info("[ADB] %s", output)
    output = execute_adb(["wait-for-local-device"])
    logger.info("[ADB] %s", output)
    logger.info("Please remove the USB device")
    return adb.device(f"{ip}:{port}")
Esempio n. 2
0
def main(device: AdbDevice = None):
    """
    Initializes the global state, sets up a ThreadPoolExecutor and launches the Nimses app.

    :param device: the device to control, if `None`, chooses the first and only device
    """
    executor = ThreadPoolExecutor(3)
    state = {
        "device": device if device is not None else
        adb.device(),  # The Android device to control
        "executor": executor,  # The executor where the magic happens
        "last_image": None,  # The last image
        "last_ad": 0,  # The amount of updates since the last ad
        "ad_closed": True,  # Whether the last ad has been closed
        "ad_time": 0  # When to close the app (in the future)
    }

    device.app_start(NIMSES_PACKAGE, NIMSES_MAIN_ACTIVITY)

    # Prepare future variable
    future = Future()
    future.set_result(None)
    while True:
        if future.done():
            future = executor.submit(lambda: log_error(lambda: handle_new_ad(
                find_inline_ads(screen_shot_android(device)), device, state)))
        sleep(0.1)
 def __init__(self, serial: str, callback=nop_callback):
     self._serial = serial
     self._procs = []
     self._current_ip = current_ip()
     self._current_ip_network = current_ip_network()
     self._device = adbclient.device(serial)
     self._callback = callback
Esempio n. 4
0
    def start(self):
        """ start device """
        self.mnc = MNCDevice(self.device_id)
        self.player = ActionPlayer(self.device_id)
        self.toolkit = PYAToolkit(self.device_id)
        self.adb_utils = adb.device(serial=self.device_id)

        logger.debug("FDevice [{}] started".format(self.device_id))
Esempio n. 5
0
def main():

    map_array = read_png("map.png")
    start_array = read_png("start.png")[200:, :, :]

    d = adb.device()

    for i in range(1000):
        print(i)
        loop_time = time()
        flag = 1

        while True:
            screen = read_png(get_screenshot(file_name="now.png"))
            os.remove("./now.png")
            # print("start_checker")
            # print(abs(start_array - screen[200:, :, :]).mean())
            # print("map_checker")
            # print(abs(map_array - screen).mean())

            if time() - loop_time > 300:
                print(str(time() - loop_time) + " has passed")
                sys.exit()

            elif abs(start_array - screen[200:, :, :]).mean() < 0.01:
                d.click(2555, 1333)
                flag += 1
                print("start_find")
                print(time() - loop_time)
                print("=" * 20)
                sleep(1)
                d.click(2430, 1000)
                print("sleeping")
                sleep(155)
                print("sleep finished")
                print(time() - loop_time)
                d.click(1500, 200)
                sleep(3)

                break
            elif abs((map_array - screen)).mean() < 0.2:
                # d.click(1920,746)
                d.click(2100, 560)
                print("map_find")
                print(time() - loop_time)
                print("=" * 20)
                print()
                sleep(0.5)
            else:
                d.click(1500, 200)
                sleep(4)
                print("pass")
    d.keyevent("HOME")
Esempio n. 6
0
    def start(self, simple_mode: bool = None):
        """ start device """
        self.mnc = MNCDevice(self.device_id)
        self.toolkit = PYAToolkit(self.device_id)

        if not simple_mode:
            self.player = ActionPlayer(self.device_id)
            self.adb_utils = adb.device(serial=self.device_id)
        else:
            self.player = AdbPlayer(self.device_id)

        logger.debug("FDevice [{}] started".format(self.device_id))
Esempio n. 7
0
    def _get_memory(self):
        try:
            if not self.is_adb_device_exist:
                self.d = adb.device()
                self.is_adb_device_exist = True
                print(id(self.d))

            self.memory = self.d.shell('dumpsys meminfo')
        except Exception as e:
            # print(f'未找到设备 或 连接不上设备 {e}')
            self.is_adb_device_exist = False
            self.memory = ''
Esempio n. 8
0
def app_install_local(serial: str, apk_path: str, launch: bool = False) -> str:
    """
    install apk to device

    Returns:
        package name

    Raises:
        AdbInstallError, FileNotFoundError
    """
    # 解析apk文件
    device = adbclient.device(serial)
    try:
        apk = apkutils.APK(apk_path)
    except apkutils.apkfile.BadZipFile:
        raise InstallError("ApkParse", "Bad zip file")

    # 提前将重名包卸载
    package_name = apk.manifest.package_name
    pkginfo = device.package_info(package_name)
    if pkginfo:
        logger.debug("uninstall: %s", package_name)
        device.uninstall(package_name)

    # 解锁手机,防止锁屏
    # ud = u2.connect_usb(serial)
    # ud.open_identify()
    try:
        # 推送到手机
        dst = "/data/local/tmp/tmp-%d.apk" % int(time.time() * 1000)
        logger.debug("push %s %s", apk_path, dst)
        device.sync.push(apk_path, dst)
        logger.debug("install-remote %s", dst)
        # 调用pm install安装
        device.install_remote(dst)
    except adbutils.errors.AdbInstallError as e:
        raise InstallError("install", e.output)
    # finally:
    # 停止uiautomator2服务
    # logger.debug("uiautomator2 stop")
    # ud.session().press("home")
    # ud.service("uiautomator").stop()

    # 启动应用
    if launch:
        logger.debug("launch %s", package_name)
        device.app_start(package_name)
    return package_name
Esempio n. 9
0
    def _get_top(self):
        # COLUMNS=512 进行宽度设置 若不设置args列显示不全
        # top -n 1
        # -m 500 最多显示500个进程
        # -s 6 按cpu使用列排序
        try:
            if not self.is_adb_device_exist:
                self.d = adb.device()
                self.is_adb_device_exist = True
                print(id(self.d))

            self.top = self.d.shell('COLUMNS=512 top -n 1 -m 500 -s 6')
        except Exception as e:
            # print(f'未找到设备 或 连接不上设备 {e}')
            self.is_adb_device_exist = False
            self.top = ''
Esempio n. 10
0
def main(argv):
    logging.basicConfig(level=logging.INFO,
                        format='%(message)s',
                        handlers=[
                            logging.FileHandler(argv[0], 'w',
                                                encoding='utf-8'),
                            logging.StreamHandler(sys.stdout)
                        ])

    frida_device = frida.get_usb_device()
    pid = frida_device.spawn(argv[1])
    session = frida_device.attach(pid)
    session.enable_jit()
    adb_device = adb.device()
    recorder = Recorder(session, adb_device)
    recorder.record()
    frida_device.resume(pid)

    print('Press ENTER to stop recording')
    sys.stdin.readline()  # Wait for exit
    recorder.close()
Esempio n. 11
0
   {Fore.MAGENTA}|   └method 2 - rooting device from bootlander (recommended)
   {Fore.MAGENTA}├readme
   {Fore.MAGENTA}├help
   {Fore.MAGENTA}└exit

{Fore.WHITE}Built with {Fore.LIGHTGREEN_EX}\U0001F40D{Fore.WHITE} and https://github.com/openatx/adbutils

{random.choice(tips)}
""")

while True:
    print(rainbowtext.text(f"""{os.getlogin()}# """), end='')
    cmd = input()
    if cmd == "connect":
        try:
            device = adb.device()
            os.system('cls || clear')
            for d in adb.device_list():
                print(
                    rainbowtext.text(f"""
Connected!
    
Serial key: {device.serial}
Operating system: {device.prop.name}
Device: {device.prop.device}
Model: {device.prop.model}
                """))
        except:
            print("No device(s) connected!")
    elif cmd == "recovery":
        try:
Esempio n. 12
0
def main():
    parser = argparse.ArgumentParser()
    # formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-s", "--serial", help="device serial number")
    parser.add_argument("-V",
                        "--server-version",
                        action="store_true",
                        help="show adb server version")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list devices")
    parser.add_argument("-i",
                        "--install",
                        help="install from local apk or url")
    parser.add_argument(
        "--install-confirm",
        action="store_true",
        help="auto confirm when install (based on uiautomator2)")
    parser.add_argument("-u", "--uninstall", help="uninstall apk")
    parser.add_argument("--qrcode", help="show qrcode of the specified file")
    parser.add_argument("--clear",
                        action="store_true",
                        help="clear all data when uninstall")
    parser.add_argument("--list-packages",
                        action="store_true",
                        help="list packages installed")
    parser.add_argument("-p",
                        "--package",
                        help="show package info in json format")
    parser.add_argument("--grep", help="filter matched package names")
    parser.add_argument("--connect", type=str, help="connect remote device")
    parser.add_argument("--shell",
                        action="store_true",
                        help="run shell command")
    parser.add_argument("--minicap",
                        action="store_true",
                        help="install minicap and minitouch to device")
    parser.add_argument("--screenshot", type=str, help="take screenshot")
    parser.add_argument("-b", "--browser", help="open browser in device")
    parser.add_argument(
        "--push",
        help=
        "push local to remote, arg is colon seperated, eg some.txt:/sdcard/s.txt"
    )
    parser.add_argument("args", nargs="*", help="arguments")

    args = parser.parse_args()

    if args.connect:
        adbclient.connect(args.connect)
        return

    if args.server_version:
        print("ADB Server version: {}".format(adbclient.server_version()))
        return

    if args.list:
        rows = []
        for d in adbclient.devices():
            rows.append([d.serial, d.shell("getprop ro.product.model")])
        lens = []
        for col in zip(*rows):
            lens.append(max([len(v) for v in col]))
        format = "  ".join(["{:<" + str(l) + "}" for l in lens])
        for row in rows:
            print(format.format(*row))
        return

    if args.qrcode:
        from http.server import ThreadingHTTPServer
        from http.server import SimpleHTTPRequestHandler

        filename = args.qrcode
        port = 8000
        url = "http://%s:%d/%s" % (current_ip(), port, filename)
        print("File URL:", url)
        try:
            import qrcode
            qr = qrcode.QRCode(border=2)
            qr.add_data(url)
            qr.print_ascii(tty=True)
        except ImportError:
            print(
                "In order to show QRCode, you need install with: pip3 install qrcode"
            )

        httpd = ThreadingHTTPServer(('', port), SimpleHTTPRequestHandler)
        httpd.serve_forever()
        return

    d = adbclient.device(args.serial)

    if args.shell:
        output = d.shell(args.args)
        print(output)
        return

    if args.install:
        dst = "/data/local/tmp/tmp-%d.apk" % (int(time.time() * 1000))
        print("push to %s" % dst)
        if re.match(r"^https?://", args.install):
            resp = requests.get(args.install, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
        else:
            length = os.stat(args.install).st_size
            fd = open(args.install, "rb")
            r = ReadProgress(fd, length)

        start = time.time()
        d.sync.push(r, dst)
        print("Success pushed, time used %d seconds" % (time.time() - start))

        new_dst = "/data/local/tmp/tmp-%s.apk" % r._hash[:8]
        d.shell(["mv", dst, new_dst])
        dst = new_dst
        info = d.sync.stat(dst)
        print("verify pushed apk, md5: %s, size: %s" %
              (r._hash, humanize(info.size)))
        assert info.size == r.copied

        print("install to android system ...")
        if args.install_confirm:
            # Beta
            import uiautomator2 as u2
            ud = u2.connect(args.serial)
            ud.press("home")
            ud.xpath.when("允许").click()
            ud.xpath.when("安装").click()
            ud.xpath.watch_background(2.0)

        for i in range(3):
            try:
                start = time.time()
                d.install_remote(dst, clean=True)
                print("Success installed, time used %d seconds" %
                      (time.time() - start))
                break
            except AdbInstallError as e:
                if i < 2 and e.reason == "INSTALL_FAILED_CANCELLED_BY_USER":
                    print("Catch error %s, reinstall" % e.reason)
                    continue
                sys.exit(
                    "Failure " + e.reason + "\n" +
                    "Remote apk is not removed. Manually install command:\n\t"
                    + "adb shell pm install -r -t " + dst)

    elif args.uninstall:
        d.shell(["pm", "uninstall", args.uninstall])

    elif args.list_packages:
        patten = re.compile(args.grep or ".*")
        for p in d.list_packages():
            if patten.search(p):
                print(p)

    elif args.screenshot:
        if args.minicap:
            json_output = d.shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-i", "2&>/dev/null"
            ]).strip()
            data = json.loads(json_output)
            w, h, r = data["width"], data["height"], data["rotation"]
            d.shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-P", "{0}x{1}@{0}x{1}/{2}".format(w, h, r), "-s",
                ">/sdcard/minicap.jpg"
            ])
            d.sync.pull("/sdcard/minicap.jpg", args.screenshot)
        else:
            remote_tmp_path = "/data/local/tmp/screenshot.png"
            d.shell(["rm", remote_tmp_path])
            d.shell(["screencap", "-p", remote_tmp_path])
            d.sync.pull(remote_tmp_path, args.screenshot)

    elif args.minicap:  # without args.screenshot
        _setup_minicap(d)

    elif args.push:
        local, remote = args.push.split(":", 1)
        length = os.stat(local).st_size
        with open(local, "rb") as fd:
            r = ReadProgress(fd, length)
            d.sync.push(r, remote, filesize=length)

    elif args.browser:
        d.open_browser(args.browser)

    elif args.package:
        info = d.package_info(args.package)
        print(json.dumps(info, indent=4))
Esempio n. 13
0
def main():
    parser = argparse.ArgumentParser()
    # formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-s", "--serial", help="device serial number")
    parser.add_argument("-V",
                        "--server-version",
                        action="store_true",
                        help="show adb server version")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list devices")
    parser.add_argument("-i",
                        "--install",
                        help="install from local apk or url")
    parser.add_argument(
        "--install-confirm",
        action="store_true",
        help="auto confirm when install (based on uiautomator2)")
    parser.add_argument("-u", "--uninstall", help="uninstall apk")
    parser.add_argument("-L",
                        "--launch",
                        action="store_true",
                        help="launch after install")
    parser.add_argument("--qrcode", help="show qrcode of the specified file")
    parser.add_argument("--clear",
                        action="store_true",
                        help="clear all data when uninstall")
    parser.add_argument("--list-packages",
                        action="store_true",
                        help="list packages installed")
    parser.add_argument("-p",
                        "--package",
                        help="show package info in json format")
    parser.add_argument("--grep", help="filter matched package names")
    parser.add_argument("--connect", type=str, help="connect remote device")
    parser.add_argument("--shell",
                        action="store_true",
                        help="run shell command")
    parser.add_argument("--minicap",
                        action="store_true",
                        help="install minicap and minitouch to device")
    parser.add_argument("--screenshot", type=str, help="take screenshot")
    parser.add_argument("-b", "--browser", help="open browser in device")
    parser.add_argument(
        "--push",
        help=
        "push local to remote, arg is colon seperated, eg some.txt:/sdcard/s.txt"
    )
    parser.add_argument(
        "--pull",
        help="push local to remote, arg is colon seperated, eg /sdcard/some.txt"
    )
    parser.add_argument("--dump-info",
                        action="store_true",
                        help="dump info for developer")
    parser.add_argument("--track",
                        action="store_true",
                        help="trace device status")
    parser.add_argument("args", nargs="*", help="arguments")

    args = parser.parse_args()

    if args.connect:
        adbclient.connect(args.connect)
        return

    if args.server_version:
        print("ADB Server version: {}".format(adbclient.server_version()))
        return

    if args.list:
        rows = []
        for d in adbclient.device_list():
            rows.append([d.serial, d.shell("getprop ro.product.model")])
        lens = []
        for col in zip(*rows):
            lens.append(max([len(v) for v in col]))
        format = "  ".join(["{:<" + str(l) + "}" for l in lens])
        for row in rows:
            print(format.format(*row))
        return

    if args.qrcode:
        from http.server import ThreadingHTTPServer
        from http.server import SimpleHTTPRequestHandler

        filename = args.qrcode
        port = 8000
        url = "http://%s:%d/%s" % (current_ip(), port, filename)
        print("File URL:", url)
        try:
            import qrcode
            qr = qrcode.QRCode(border=2)
            qr.add_data(url)
            qr.print_ascii(tty=True)
        except ImportError:
            print(
                "In order to show QRCode, you need install with: pip3 install qrcode"
            )

        httpd = ThreadingHTTPServer(('', port), SimpleHTTPRequestHandler)
        httpd.serve_forever()
        return

    if args.dump_info:
        print("==== ADB Info ====")
        print("Path:", adbutils.adb_path())
        print("Server version:", adbclient.server_version())
        print("")
        print(">> List of devices attached")
        for d in adbclient.device_list():
            print("-", d.serial, d.prop.name, d.prop.model)
        return

    if args.track:
        for event in adbclient.track_devices():
            asctime = datetime.datetime.now().strftime("%H:%M:%S.%f")
            print("{} {} -> {}".format(asctime[:-3], event.serial,
                                       event.status))
        return

    ## Device operation
    d = adbclient.device(args.serial)

    if args.shell:
        output = d.shell(args.args)
        print(output)
        return

    if args.install:
        if re.match(r"^https?://", args.install):
            resp = requests.get(args.install, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
            print("tmpfile path:", r.filepath())
        else:
            length = os.stat(args.install).st_size
            fd = open(args.install, "rb")
            r = ReadProgress(fd, length, source_path=args.install)

        dst = "/data/local/tmp/tmp-%d.apk" % (int(time.time() * 1000))
        print("push to %s" % dst)

        start = time.time()
        d.sync.push(r, dst)

        # parse apk package-name
        apk = apkutils2.APK(r.filepath())
        package_name = apk.manifest.package_name
        main_activity = apk.manifest.main_activity
        version_name = apk.manifest.version_name
        print("packageName:", package_name)
        print("mainActivity:", main_activity)
        print("apkVersion: {}".format(version_name))
        print("success pushed, time used %d seconds" % (time.time() - start))

        new_dst = "/data/local/tmp/{}-{}.apk".format(package_name,
                                                     version_name)
        d.shell(["mv", dst, new_dst])
        dst = new_dst
        info = d.sync.stat(dst)
        print("verify pushed apk, md5: %s, size: %s" %
              (r._hash, humanize(info.size)))
        assert info.size == r.copied

        print("install to android system ...")
        if args.install_confirm:
            # Beta
            import uiautomator2 as u2
            ud = u2.connect(args.serial)
            ud.press("home")
            ud.watcher.when("继续安装").click()
            ud.watcher.when("允许").click()
            ud.watcher.when("安装").click()
            ud.watcher.start(2.0)

        try:
            start = time.time()
            d.install_remote(dst, clean=True)
            print("Success installed, time used %d seconds" %
                  (time.time() - start))
            if args.launch:
                print("Launch app: %s/%s" % (package_name, main_activity))
                d.shell(
                    ['am', 'start', '-n', package_name + "/" + main_activity])

        except AdbInstallError as e:
            if e.reason in [
                    "INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE",
                    "INSTALL_FAILED_UPDATE_INCOMPATIBLE",
                    "INSTALL_FAILED_VERSION_DOWNGRADE"
            ]:
                print("uninstall %s because %s" % (package_name, e.reason))
                d.uninstall(package_name)
                d.install_remote(dst, clean=True)
                print("Success installed, time used %d seconds" %
                      (time.time() - start))
            elif e.reason == "INSTALL_FAILED_CANCELLED_BY_USER":
                print("Catch error %s, reinstall" % e.reason)
                d.install_remote(dst, clean=True)
                print("Success installed, time used %d seconds" %
                      (time.time() - start))
            else:
                sys.exit(
                    "Failure " + e.reason + "\n" +
                    "Remote apk is not removed. Manually install command:\n\t"
                    + "adb shell pm install -r -t " + dst)

    elif args.uninstall:
        d.shell(["pm", "uninstall", args.uninstall])

    elif args.list_packages:
        patten = re.compile(args.grep or ".*")
        for p in d.list_packages():
            if patten.search(p):
                print(p)

    elif args.screenshot:
        if args.minicap:

            def adb_shell(cmd: list):
                print("Run:", " ".join(["adb", "shell"] + cmd))
                return d.shell(cmd).strip()

            json_output = adb_shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-i", "2&>/dev/null"
            ])
            if not json_output.startswith("{"):
                raise RuntimeError("Invalid json format", json_output)
            data = json.loads(json_output)

            w, h, r = data["width"], data["height"], data["rotation"]
            d.shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-P", "{0}x{1}@{0}x{1}/{2}".format(w, h, r), "-s",
                ">/sdcard/minicap.jpg"
            ])
            d.sync.pull("/sdcard/minicap.jpg", args.screenshot)
        else:
            remote_tmp_path = "/data/local/tmp/screenshot.png"
            d.shell(["rm", remote_tmp_path])
            d.shell(["screencap", "-p", remote_tmp_path])
            d.sync.pull(remote_tmp_path, args.screenshot)

    elif args.minicap:  # without args.screenshot
        _setup_minicap(d)

    elif args.push:
        local, remote = args.push.split(":", 1)
        length = os.stat(local).st_size
        with open(local, "rb") as fd:
            r = ReadProgress(fd, length)
            d.sync.push(r, remote, filesize=length)

    elif args.pull:
        remote_path = args.pull
        target_path = os.path.basename(remote_path)
        finfo = d.sync.stat(args.pull)

        if finfo.mode == 0 and finfo.size == 0:
            sys.exit(f"remote file '{remote_path}' does not exist")

        bytes_so_far = 0
        for chunk in d.sync.iter_content(remote_path):
            bytes_so_far += len(chunk)
            percent = bytes_so_far / finfo.size * 100 if finfo.size != 0 else 100.0
            print(
                f"\rDownload to {target_path} ... [{bytes_so_far} / {finfo.size}] %.1f %%"
                % percent,
                end="",
                flush=True)
        print(f"{remote_path} pulled to {target_path}")

    elif args.browser:
        d.open_browser(args.browser)

    elif args.package:
        info = d.package_info(args.package)
        print(json.dumps(info, indent=4))
Esempio n. 14
0
def main():
    parser = argparse.ArgumentParser()
    # formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-s", "--serial", help="device serial number")
    parser.add_argument("-V",
                        "--server-version",
                        action="store_true",
                        help="show adb server version")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list devices")
    parser.add_argument("-i",
                        "--install",
                        help="install from local apk or url")
    parser.add_argument(
        "--install-confirm",
        action="store_true",
        help="auto confirm when install (based on uiautomator2)")
    parser.add_argument("-u", "--uninstall", help="uninstall apk")
    parser.add_argument("-L",
                        "--launch",
                        action="store_true",
                        help="launch after install")
    parser.add_argument("--qrcode", help="show qrcode of the specified file")
    parser.add_argument("--clear",
                        action="store_true",
                        help="clear all data when uninstall")
    parser.add_argument("--list-packages",
                        action="store_true",
                        help="list packages installed")
    parser.add_argument("--current",
                        action="store_true",
                        help="show current package info")
    parser.add_argument("-p",
                        "--package",
                        help="show package info in json format")
    parser.add_argument("--grep", help="filter matched package names")
    parser.add_argument("--connect", type=str, help="connect remote device")
    parser.add_argument("--shell",
                        action="store_true",
                        help="run shell command")
    parser.add_argument("--minicap",
                        action="store_true",
                        help="install minicap and minitouch to device")
    parser.add_argument("--screenshot", type=str, help="take screenshot")
    parser.add_argument("-b", "--browser", help="open browser in device")
    parser.add_argument(
        "--push",
        help=
        "push local to remote, arg is colon seperated, eg some.txt:/sdcard/s.txt"
    )
    parser.add_argument(
        "--pull",
        help="push local to remote, arg is colon seperated, eg /sdcard/some.txt"
    )
    parser.add_argument("--dump-info",
                        action="store_true",
                        help="dump info for developer")
    parser.add_argument("--track",
                        action="store_true",
                        help="trace device status")
    parser.add_argument("args", nargs="*", help="arguments")

    args = parser.parse_args()

    if args.connect:
        adbclient.connect(args.connect)
        return

    if args.server_version:
        print("ADB Server version: {}".format(adbclient.server_version()))
        return

    if args.list:
        rows = []
        for d in adbclient.device_list():
            rows.append([d.serial, d.shell("getprop ro.product.model")])
        lens = []
        for col in zip(*rows):
            lens.append(max([len(v) for v in col]))
        format = "  ".join(["{:<" + str(l) + "}" for l in lens])
        for row in rows:
            print(format.format(*row))
        return

    if args.qrcode:
        from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer

        filename = args.qrcode
        port = 8000
        url = "http://%s:%d/%s" % (current_ip(), port, filename)
        print("File URL:", url)
        try:
            import qrcode
            qr = qrcode.QRCode(border=2)
            qr.add_data(url)
            qr.print_ascii(tty=True)
        except ImportError:
            print(
                "In order to show QRCode, you need install with: pip3 install qrcode"
            )

        httpd = ThreadingHTTPServer(('', port), SimpleHTTPRequestHandler)
        httpd.serve_forever()
        return

    if args.dump_info:
        print("==== ADB Info ====")
        print("Path:", adbutils.adb_path())
        print("Server version:", adbclient.server_version())
        print("")
        print(">> List of devices attached")
        for d in adbclient.device_list():
            print("-", d.serial, d.prop.name, d.prop.model)
        return

    if args.track:
        for event in adbclient.track_devices():
            asctime = datetime.datetime.now().strftime("%H:%M:%S.%f")
            print("{} {} -> {}".format(asctime[:-3], event.serial,
                                       event.status))
        return

    ## Device operation
    d = adbclient.device(args.serial)

    if args.shell:
        output = d.shell(args.args)
        print(output)
        return

    if args.install:

        def _callback(event_name: str, ud):
            name = "_INSTALL_"
            if event_name == "BEFORE_INSTALL":
                print("== Enable popup window watcher")
                ud.press("home")
                ud.watcher(name).when("允许").click()
                ud.watcher(name).when("继续安装").click()
                ud.watcher(name).when("安装").click()
                ud.watcher.start()
            elif event_name == "FINALLY":
                print("== Stop popup window watcher")
                ud.watcher.remove(name)
                ud.watcher.stop()

        if args.install_confirm:
            import uiautomator2 as u2
            ud = u2.connect(args.serial)
            _callback = functools.partial(_callback, ud=ud)
        else:
            _callback = None

        d.install(args.install, uninstall=True, callback=_callback)

    elif args.uninstall:
        d.uninstall(args.uninstall)

    elif args.list_packages:
        patten = re.compile(args.grep or ".*")
        for p in d.list_packages():
            if patten.search(p):
                print(p)

    elif args.screenshot:
        if args.minicap:

            def adb_shell(cmd: list):
                print("Run:", " ".join(["adb", "shell"] + cmd))
                return d.shell(cmd).strip()

            json_output = adb_shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-i", "2&>/dev/null"
            ])
            if not json_output.startswith("{"):
                raise RuntimeError("Invalid json format", json_output)
            data = json.loads(json_output)

            w, h, r = data["width"], data["height"], data["rotation"]
            d.shell([
                "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap",
                "-P", "{0}x{1}@{0}x{1}/{2}".format(w, h, r), "-s",
                ">/sdcard/minicap.jpg"
            ])
            d.sync.pull("/sdcard/minicap.jpg", args.screenshot)
        else:
            remote_tmp_path = "/data/local/tmp/screenshot.png"
            d.shell(["rm", remote_tmp_path])
            d.shell(["screencap", "-p", remote_tmp_path])
            d.sync.pull(remote_tmp_path, args.screenshot)

    elif args.minicap:  # without args.screenshot
        _setup_minicap(d)

    elif args.push:
        local, remote = args.push.split(":", 1)
        length = os.stat(local).st_size
        with open(local, "rb") as fd:
            r = ReadProgress(fd, length)
            d.sync.push(r, remote, filesize=length)

    elif args.pull:
        remote_path = args.pull
        target_path = os.path.basename(remote_path)
        finfo = d.sync.stat(args.pull)

        if finfo.mode == 0 and finfo.size == 0:
            sys.exit(f"remote file '{remote_path}' does not exist")

        bytes_so_far = 0
        for chunk in d.sync.iter_content(remote_path):
            bytes_so_far += len(chunk)
            percent = bytes_so_far / finfo.size * 100 if finfo.size != 0 else 100.0
            print(
                f"\rDownload to {target_path} ... [{bytes_so_far} / {finfo.size}] %.1f %%"
                % percent,
                end="",
                flush=True)
        print(f"{remote_path} pulled to {target_path}")

    elif args.browser:
        d.open_browser(args.browser)

    elif args.current:
        package_name = d.current_app()['package']
        info = d.package_info(package_name)
        print(json.dumps(info, indent=4, default=str))
    elif args.package:
        info = d.package_info(args.package)
        print(json.dumps(info, indent=4, default=str))
Esempio n. 15
0
import time
import json
from adbutils import adb

d = adb.device(serial="localhost:5555")

def screenshot(path):
    remote_tmp_path = "/data/local/tmp/screenshot.png"
    d.shell(["rm", remote_tmp_path])
    d.shell(["screencap", "-p", remote_tmp_path])
    d.sync.pull(remote_tmp_path, 'run/'+path)


# @sio.on('Click')
def on_click(data):
    print(data)
    screenshot("r_click_"+str(data["timestamp"])+".png")
    d.click(data["x"],data["y"])


# @sio.on('KeyInput')
def on_input(data):
    print(''.join([chr(data["keycode"])]))
    d.send_keys(''.join([chr(data["keycode"])]))


# @sio.on('KeyEvent')
def on_event(data):
    print(data)
    d.keyevent(data["keycode"])
Esempio n. 16
0
def main():
    parser = argparse.ArgumentParser()
    # formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-s", "--serial", help="device serial number")
    parser.add_argument("-V",
                        "--server-version",
                        action="store_true",
                        help="show adb server version")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list devices")
    parser.add_argument("-i",
                        "--install",
                        help="install from local apk or url")
    parser.add_argument("-u", "--uninstall", help="uninstall apk")
    parser.add_argument("--clear",
                        action="store_true",
                        help="clear all data when uninstall")
    parser.add_argument("--list-packages",
                        action="store_true",
                        help="list packages installed")
    parser.add_argument("--grep", help="filter matched package names")
    parser.add_argument("--connect", type=str, help="connect remote device")
    parser.add_argument("--shell",
                        action="store_true",
                        help="run shell command")
    parser.add_argument("--minicap",
                        action="store_true",
                        help="install minicap and minitouch to device")
    parser.add_argument("--screenshot", type=str, help="take screenshot")
    parser.add_argument("args", nargs="*", help="arguments")

    args = parser.parse_args()

    if args.connect:
        adbclient.connect(args.connect)
        return

    if args.server_version:
        print("ADB Server version: {}".format(adbclient.server_version()))
        return

    if args.list:
        rows = []
        for d in adbclient.devices():
            rows.append([d.serial, d.shell("getprop ro.product.model")])
        lens = []
        for col in zip(*rows):
            lens.append(max([len(v) for v in col]))
        format = "  ".join(["{:<" + str(l) + "}" for l in lens])
        for row in rows:
            print(format.format(*row))
        return

    d = adbclient.device(args.serial)

    if args.shell:
        output = d.shell(args.args)
        print(output)
        return

    if args.install:
        dst = "/data/local/tmp/tmp-%d.apk" % (int(time.time() * 1000))
        print("push to %s" % dst)
        if re.match(r"^https?://", args.install):
            resp = requests.get(args.install, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
        else:
            length = os.stat(args.install).st_size
            fd = open(args.install, "rb")
            r = ReadProgress(fd, length)

        start = time.time()
        d.sync.push(r, dst)
        print("Success pushed, time used %d seconds" % (time.time() - start))

        new_dst = "/data/local/tmp/tmp-%s.apk" % r._hash[:8]
        d.shell(["mv", dst, new_dst])
        dst = new_dst
        info = d.sync.stat(dst)
        print("verify pushed apk, md5: %s, size: %s" %
              (r._hash, humanize(info.size)))
        assert info.size == r.copied

        print("install to android system ...")
        try:
            start = time.time()
            d.install_remote(dst, clean=True)
            print("Success installed, time used %d seconds" %
                  (time.time() - start))
        except AdbInstallError as e:
            sys.exit(
                "Failure " + e.reason + "\n" +
                "Remote apk is not removed. Manually install command:\n\t" +
                "adb shell pm install -r -t " + dst)

    elif args.uninstall:
        d.shell(["pm", "uninstall", args.uninstall])

    elif args.list_packages:
        patten = re.compile(args.grep or ".*")
        for p in d.list_packages():
            if patten.search(p):
                print(p)

    elif args.minicap:

        def cache_download(url, dst):
            if os.path.exists(dst):
                print("Use cached", dst)
                return
            print("Download {} from {}".format(dst, url))
            resp = requests.get(url, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
            with open(dst + ".cached", "wb") as f:
                shutil.copyfileobj(r, f)
            shutil.move(dst + ".cached", dst)

        def push_zipfile(path: str,
                         dest: str,
                         mode=0o755,
                         zipfile_path: str = "vendor/stf-binaries-master.zip"):
            """ push minicap and minitouch from zip """
            with zipfile.ZipFile(zipfile_path) as z:
                if path not in z.namelist():
                    print("WARNING: stf stuff %s not found", path)
                    return
                with z.open(path) as f:
                    d.sync.push(f, dest, mode)

        zipfile_path = "stf-binaries.zip"
        cache_download(
            "https://github.com/openatx/stf-binaries/archive/0.2.zip",
            zipfile_path)
        zip_folder = "stf-binaries-0.2"

        sdk = d.getprop("ro.build.version.sdk")  # eg 26
        abi = d.getprop('ro.product.cpu.abi')  # eg arm64-v8a
        abis = (d.getprop('ro.product.cpu.abilist').strip() or abi).split(",")
        # return
        print("sdk: %s, abi: %s, support-abis: %s" %
              (sdk, abi, ','.join(abis)))
        print("Push minicap+minicap.so to device")
        prefix = zip_folder + "/node_modules/minicap-prebuilt/prebuilt/"
        push_zipfile(prefix + abi + "/lib/android-" + sdk + "/minicap.so",
                     "/data/local/tmp/minicap.so", 0o644, zipfile_path)
        push_zipfile(prefix + abi + "/bin/minicap", "/data/local/tmp/minicap",
                     0o0755, zipfile_path)

        print("Push minitouch to device")
        prefix = zip_folder + "/node_modules/minitouch-prebuilt/prebuilt/"
        push_zipfile(prefix + abi + "/bin/minitouch",
                     "/data/local/tmp/minitouch", 0o0755, zipfile_path)

        # check if minicap installed
        output = d.shell([
            "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap", "-i"
        ])
        print(output)
        print(
            "If you see JSON output, it means minicap installed successfully")

    if args.screenshot:
        remote_tmp_path = "/data/local/tmp/screenshot.png"
        d.shell(["rm", remote_tmp_path])
        d.shell(["screencap", "-p", remote_tmp_path])
        d.sync.pull(remote_tmp_path, args.screenshot)
Esempio n. 17
0
def device():
    print("Fixture device")
    return adb.device()
Esempio n. 18
0
import png
from adbutils import adb
import os
import numpy
import itertools
import matplotlib.pyplot as plt
from playgame import *
import csv
import time

os.system("adb start-server")
d = adb.device()


def main():
    while True:
        print("Capturing")
        d.shell("screencap -p /sdcard/block.png")
        d.sync.pull("/sdcard/block.png", "block.png")
        char_grid, left, top, size = get_grid_from_file("block.png")
        left += size / 2
        top += size / 2
        print(left, top, size)
        print_grid(char_grid)
        save_grid(char_grid, "block.txt")
        os.system("./unblock block.txt commands.txt")

        commands = " "
        with open("commands.txt") as csv_file:
            csv_reader = csv.reader(csv_file, delimiter=',')
            line_count = 0
Esempio n. 19
0
import socketio
import time
from adbutils import adb
from aiohttp import web
import json
from repeat import read_file
import base64
sio = socketio.AsyncServer(cors_allowed_origins='*')
app = web.Application()
sio.attach(app)

d = adb.device('localhost:5555')
r = d.screenrecord(no_autostart=True)

actions = []
action = ""
paramStart = {}
paramEnd = {}

asciiToAdb = {
    8: 67,  # Backspace
    9: 61,  # Tab
    13: 66,  # Enter
    27: 4,  #Escape: Back
    37: 21,  # Left arrow
    38: 19,  # Up arrow
    39: 22,  # Right arrow
    40: 20,  # Down arrow
    46: 67,  #Delete
}
Esempio n. 20
0
def app_install_local(serial: str, apk_path: str, launch: bool = False) -> str:
    """
    install apk to device

    Returns:
        package name

    Raises:
        AdbInstallError, FileNotFoundError
    """
    # 解析apk文件
    device = adbclient.device(serial)
    try:
        apk = apkutils.APK(apk_path)
    except apkutils.apkfile.BadZipFile:
        raise InstallError("ApkParse", "Bad zip file")

    # 提前将重名包卸载
    package_name = apk.manifest.package_name
    pkginfo = device.package_info(package_name)
    if pkginfo:
        logger.debug("uninstall: %s", package_name)
        device.uninstall(package_name)

    # 解锁手机,防止锁屏
    # ud = u2.connect_usb(serial)
    # ud.open_identify()
    try:
        # 推送到手机
        dst = "/data/local/tmp/tmp-%d.apk" % int(time.time() * 1000)
        logger.debug("push %s %s", apk_path, dst)
        device.sync.push(apk_path, dst)
        logger.debug("install-remote %s", dst)

        if platform.system() == 'Linux':
            cmd = "sudo adb shell getprop ro.product.brand"
        else:
            cmd = "adb shell getprop ro.product.brand"

        brand = os.popen(cmd).read()
        logger.debug("app_install_local: device brand is ===>>> %s", brand)

        if 'vivo' in brand.lower() or 'oppo' in brand.lower():
            logger.debug("f**k %s!!!", brand.lower())
            t1 = threading.Thread(target=fuck_vivo_oppo)
            t1.start()

        # 调用pm install安装
        device.install_remote(dst, flags=["-r", "-t", "-g"])
    except adbutils.errors.AdbInstallError as e:
        raise InstallError("install", e.output)
    # finally:
    # 停止uiautomator2服务
    # logger.debug("uiautomator2 stop")
    # ud.session().press("home")
    # ud.service("uiautomator").stop()

    # 启动应用
    if launch:
        logger.debug("launch %s", package_name)
        device.app_start(package_name)
    return package_name
Esempio n. 21
0
        image = Image.open(BytesIO(frame_data))
        img_bytes = BytesIO()
        image.save(img_bytes, format='bmp')
        # 传到指定RK
        dev = self.devs[phone - 1]
        img_bytes.seek(0)
        dev.sync.push(img_bytes, rk_frame_path)
        # 切换Frame
        dev.shell("vcam_ctl %s %s" % (rk_cam_path, rk_frame_path))
        return True


if __name__ == '__main__':
    if os.geteuid() != 0:
        print('ERR: Must run by root')
        exit(1)
    if len(sys.argv) != 3:
        print("usage: %s <host> <port>" % sys.argv[0])
        exit(1)
    for ser in CamServerHandler.dev_sers:
        print("switch '%s' to root" % ser)
        os.system("adb -s %s root" % ser)
    time.sleep(3)
    for ser in CamServerHandler.dev_sers:
        CamServerHandler.devs.append(adb.device(serial=ser))

    host, port = sys.argv[1], int(sys.argv[2])
    addr = (host, port)
    server = ThreadingTCPServer(addr, CamServerHandler)
    print("# start...")
    server.serve_forever()
Esempio n. 22
0
def main():
    parser = argparse.ArgumentParser()
    # formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-s", "--serial", help="device serial number")
    parser.add_argument("-V",
                        "--server-version",
                        action="store_true",
                        help="show adb server version")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        help="list devices")
    parser.add_argument("-i",
                        "--install",
                        help="install from local apk or url")
    parser.add_argument("--install-confirm", action="store_true", help="auto confirm when install (based on uiautomator2)")
    parser.add_argument("-u", "--uninstall", help="uninstall apk")
    parser.add_argument("--qrcode", help="show qrcode of the specified file")
    parser.add_argument("--clear",
                        action="store_true",
                        help="clear all data when uninstall")
    parser.add_argument("--list-packages",
                        action="store_true",
                        help="list packages installed")
    parser.add_argument("-p",
                        "--package",
                        help="show package info in json format")
    parser.add_argument("--grep", help="filter matched package names")
    parser.add_argument("--connect", type=str, help="connect remote device")
    parser.add_argument("--shell",
                        action="store_true",
                        help="run shell command")
    parser.add_argument("--minicap",
                        action="store_true",
                        help="install minicap and minitouch to device")
    parser.add_argument("--screenshot", type=str, help="take screenshot")
    parser.add_argument("-b", "--browser", help="open browser in device")
    parser.add_argument("--push", help="push local to remote, arg is colon seperated, eg some.txt:/sdcard/s.txt")
    parser.add_argument("args", nargs="*", help="arguments")

    args = parser.parse_args()

    if args.connect:
        adbclient.connect(args.connect)
        return

    if args.server_version:
        print("ADB Server version: {}".format(adbclient.server_version()))
        return

    if args.list:
        rows = []
        for d in adbclient.devices():
            rows.append([d.serial, d.shell("getprop ro.product.model")])
        lens = []
        for col in zip(*rows):
            lens.append(max([len(v) for v in col]))
        format = "  ".join(["{:<" + str(l) + "}" for l in lens])
        for row in rows:
            print(format.format(*row))
        return

    if args.qrcode:
        from http.server import ThreadingHTTPServer
        from http.server import SimpleHTTPRequestHandler

        filename = args.qrcode
        port = 8000
        url = "http://%s:%d/%s" % (current_ip(), port, filename)
        print("File URL:", url)
        try:
            import qrcode
            qr = qrcode.QRCode(border=2)
            qr.add_data(url)
            qr.print_ascii(tty=True)
        except ImportError:
            print("In order to show QRCode, you need install with: pip3 install qrcode")

        httpd = ThreadingHTTPServer(('', port), SimpleHTTPRequestHandler)
        httpd.serve_forever()
        return

    d = adbclient.device(args.serial)

    if args.shell:
        output = d.shell(args.args)
        print(output)
        return

    if args.install:
        dst = "/data/local/tmp/tmp-%d.apk" % (int(time.time() * 1000))
        print("push to %s" % dst)
        if re.match(r"^https?://", args.install):
            resp = requests.get(args.install, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
        else:
            length = os.stat(args.install).st_size
            fd = open(args.install, "rb")
            r = ReadProgress(fd, length)

        start = time.time()
        d.sync.push(r, dst)
        print("Success pushed, time used %d seconds" % (time.time() - start))

        new_dst = "/data/local/tmp/tmp-%s.apk" % r._hash[:8]
        d.shell(["mv", dst, new_dst])
        dst = new_dst
        info = d.sync.stat(dst)
        print("verify pushed apk, md5: %s, size: %s" %
              (r._hash, humanize(info.size)))
        assert info.size == r.copied

        print("install to android system ...")
        if args.install_confirm:
            # Beta
            import uiautomator2 as u2
            ud = u2.connect(args.serial)
            ud.press("home")
            ud.xpath.when("允许").click()
            ud.xpath.when("安装").click()
            ud.xpath.watch_background(2.0)

        for i in range(3):
            try:
                start = time.time()
                d.install_remote(dst, clean=True)
                print("Success installed, time used %d seconds" %
                    (time.time() - start))
                break
            except AdbInstallError as e:
                if i < 2 and e.reason == "INSTALL_FAILED_CANCELLED_BY_USER":
                    print("Catch error %s, reinstall" % e.reason)
                    continue
                sys.exit(
                    "Failure " + e.reason + "\n" +
                    "Remote apk is not removed. Manually install command:\n\t" +
                    "adb shell pm install -r -t " + dst)

    elif args.uninstall:
        d.shell(["pm", "uninstall", args.uninstall])

    elif args.list_packages:
        patten = re.compile(args.grep or ".*")
        for p in d.list_packages():
            if patten.search(p):
                print(p)

    elif args.minicap:

        def cache_download(url, dst):
            if os.path.exists(dst):
                print("Use cached", dst)
                return
            print("Download {} from {}".format(dst, url))
            resp = requests.get(url, stream=True)
            resp.raise_for_status()
            length = int(resp.headers.get("Content-Length", 0))
            r = ReadProgress(resp.raw, length)
            with open(dst + ".cached", "wb") as f:
                shutil.copyfileobj(r, f)
            shutil.move(dst + ".cached", dst)

        def push_zipfile(path: str,
                         dest: str,
                         mode=0o755,
                         zipfile_path: str = "vendor/stf-binaries-master.zip"):
            """ push minicap and minitouch from zip """
            with zipfile.ZipFile(zipfile_path) as z:
                if path not in z.namelist():
                    print("WARNING: stf stuff %s not found", path)
                    return
                with z.open(path) as f:
                    d.sync.push(f, dest, mode)

        zipfile_path = "stf-binaries.zip"
        cache_download(
            "https://github.com/openatx/stf-binaries/archive/0.2.zip",
            zipfile_path)
        zip_folder = "stf-binaries-0.2"

        sdk = d.getprop("ro.build.version.sdk")  # eg 26
        abi = d.getprop('ro.product.cpu.abi')  # eg arm64-v8a
        abis = (d.getprop('ro.product.cpu.abilist').strip() or abi).split(",")
        # return
        print("sdk: %s, abi: %s, support-abis: %s" %
              (sdk, abi, ','.join(abis)))
        print("Push minicap+minicap.so to device")
        prefix = zip_folder + "/node_modules/minicap-prebuilt/prebuilt/"
        push_zipfile(prefix + abi + "/lib/android-" + sdk + "/minicap.so",
                     "/data/local/tmp/minicap.so", 0o644, zipfile_path)
        push_zipfile(prefix + abi + "/bin/minicap", "/data/local/tmp/minicap",
                     0o0755, zipfile_path)

        print("Push minitouch to device")
        prefix = zip_folder + "/node_modules/minitouch-prebuilt/prebuilt/"
        push_zipfile(prefix + abi + "/bin/minitouch",
                     "/data/local/tmp/minitouch", 0o0755, zipfile_path)

        # check if minicap installed
        output = d.shell([
            "LD_LIBRARY_PATH=/data/local/tmp", "/data/local/tmp/minicap", "-i"
        ])
        print(output)
        print(
            "If you see JSON output, it means minicap installed successfully")

    elif args.screenshot:
        remote_tmp_path = "/data/local/tmp/screenshot.png"
        d.shell(["rm", remote_tmp_path])
        d.shell(["screencap", "-p", remote_tmp_path])
        d.sync.pull(remote_tmp_path, args.screenshot)

    elif args.push:
        local, remote = args.push.split(":", 1)
        length = os.stat(local).st_size
        with open(local, "rb") as fd:
            r = ReadProgress(fd, length)
            d.sync.push(r, remote, filesize=length)

    elif args.browser:
        d.open_browser(args.browser)

    elif args.package:
        info = d.package_info(args.package)
        print(json.dumps(info, indent=4))