You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.3 KiB
118 lines
4.3 KiB
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
adb_swipe_norm.py
|
|
-----------------
|
|
Use normalized (0~1) coordinates and distance to perform an ADB swipe that adapts to any screen resolution.
|
|
|
|
Examples:
|
|
python adb_swipe_norm.py --dir down
|
|
python adb_swipe_norm.py --x 0.731156 --y 0.0102157 --dir down --dist 0.5 --duration 300
|
|
python adb_swipe_norm.py --dir up --dist 0.4
|
|
python adb_swipe_norm.py --device <serial> --dir down
|
|
|
|
Author: ChatGPT
|
|
"""
|
|
|
|
import argparse
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from typing import Optional, Tuple
|
|
|
|
def run_adb(cmd: list, device: Optional[str] = None) -> subprocess.CompletedProcess:
|
|
full = ["adb"]
|
|
if device:
|
|
full += ["-s", device]
|
|
full += cmd
|
|
return subprocess.run(full, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=False)
|
|
|
|
def ensure_device(device: Optional[str]) -> None:
|
|
# Make sure adb is available and at least one device (or the specified one) is connected
|
|
try:
|
|
out = run_adb(["devices"]).stdout.strip().splitlines()
|
|
except FileNotFoundError:
|
|
print("Error: 'adb' not found. Please install Android Platform Tools and ensure 'adb' is in PATH.")
|
|
sys.exit(1)
|
|
|
|
devices = [line.split()[0] for line in out[1:] if line.strip() and "\tdevice" in line]
|
|
if device:
|
|
if device not in devices:
|
|
print(f"Error: device '{device}' not found. Connected devices: {devices or '[]'}")
|
|
sys.exit(1)
|
|
else:
|
|
if not devices:
|
|
print("Error: no connected devices. Run 'adb devices' to verify.")
|
|
sys.exit(1)
|
|
|
|
def get_screen_size(device: Optional[str] = None) -> Tuple[int, int]:
|
|
# Try wm size first
|
|
res = run_adb(["shell", "wm", "size"], device=device)
|
|
m = re.search(r"(\d+)\s*x\s*(\d+)", res.stdout)
|
|
if m:
|
|
w, h = int(m.group(1)), int(m.group(2))
|
|
return w, h
|
|
|
|
# Fallback: dumpsys display
|
|
res = run_adb(["shell", "dumpsys", "display"], device=device)
|
|
m = re.search(r"(\d+)\s*x\s*(\d+)", res.stdout)
|
|
if m:
|
|
w, h = int(m.group(1)), int(m.group(2))
|
|
return w, h
|
|
|
|
print("Error: failed to detect screen size via 'wm size' or 'dumpsys display'.")
|
|
sys.exit(1)
|
|
|
|
def clamp01(v: float) -> float:
|
|
return max(0.0, min(1.0, v))
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="ADB swipe with normalized coordinates (0~1) adapting to any screen size.")
|
|
parser.add_argument("--x", type=float, default=0.5, help="Normalized start x in [0,1]. Default: 0.5 (center).")
|
|
parser.add_argument("--y", type=float, default=0.2, help="Normalized start y in [0,1]. Default: 0.2 (upper area).")
|
|
parser.add_argument("--dir", choices=["up", "down", "left", "right"], default="down", help="Swipe direction. Default: down.")
|
|
parser.add_argument("--dist", type=float, default=0.6, help="Swipe distance as fraction of screen (0~1). Default: 0.6.")
|
|
parser.add_argument("--duration", type=int, default=300, help="Swipe duration in milliseconds. Default: 300.")
|
|
parser.add_argument("--device", type=str, default=None, help="ADB device serial (optional).")
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Validate and clamp
|
|
sx_n = clamp01(args.x)
|
|
sy_n = clamp01(args.y)
|
|
dist = max(0.0, min(1.0, args.dist))
|
|
|
|
ensure_device(args.device)
|
|
width, height = get_screen_size(device=args.device)
|
|
|
|
# Convert normalized start point to pixels
|
|
sx = int(round(sx_n * width))
|
|
sy = int(round(sy_n * height))
|
|
|
|
# Compute end point based on direction & distance
|
|
ex, ey = sx, sy
|
|
if args.dir == "down":
|
|
ey = sy + int(round(height * dist))
|
|
elif args.dir == "up":
|
|
ey = sy - int(round(height * dist))
|
|
elif args.dir == "right":
|
|
ex = sx + int(round(width * dist))
|
|
elif args.dir == "left":
|
|
ex = sx - int(round(width * dist))
|
|
|
|
# Clamp endpoints to screen bounds just in case
|
|
ex = max(0, min(width - 1, ex))
|
|
ey = max(0, min(height - 1, ey))
|
|
|
|
# Build and run adb command
|
|
cmd = ["shell", "input", "swipe", str(sx), str(sy), str(ex), str(ey), str(args.duration)]
|
|
res = run_adb(cmd, device=args.device)
|
|
|
|
if res.returncode != 0:
|
|
print("ADB error:", res.stderr.strip() or res.stdout.strip())
|
|
sys.exit(res.returncode)
|
|
|
|
print(f"OK: swipe {args.dir} from ({sx},{sy}) to ({ex},{ey}) in {args.duration} ms on {width}x{height}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|