摘要:本文是针对安卓自动化测试(特别是小米设备)的深度实战总结。涵盖环境配置ADB 连接Root 权限获取(Magisk)脚本编写技巧及各类“疑难杂症”的解决方案。


⚠️ 第一章:小米手机“避坑”必读 (生死攸关)

在开始任何操作前,请务必修改以下设置,这是无数次失败换来的血泪经验:

  1. 🚫 关闭睡眠模式:解决手机夜间自动断开 WiFi 的问题。
    • 路径:设置 → 场景配置 → 关闭睡眠模式
  2. 🚫 关闭防误触模式:防止手机屏幕朝下或被遮挡时无法解锁运行任务。
    • 路径:设置 → 锁屏 → 关闭防误触模式
  3. 🔓 关闭 USB 安装弹窗 & 权限监控至关重要,否则每次安装都会被系统拦截。
  4. 🔄 版本一致性:多平台控制时,PC 端与手机端的 uiautomator2 版本必须保持一致。
  5. ⏳ 停用 USB 授权超时:防止长时间调试后授权失效。
  6. 推荐安卓11以上(有无限调试),存储128g极以上的手机

📦 第二章:工具准备与 ADB 连接

2.1 基础环境安装

在终端执行以下命令安装核心库:

# 安装/更新 Uiautomator2
pip install --pre -U uiautomator2

# 安装元素定位工具 Weditor
pip install --pre weditor

2.2 模拟器连接 ADB

推荐使用 Scrcpy 自带的 ADB,兼容性更佳。

技巧:如果使用逍遥/雷电模拟器,建议将 Scrcpy 目录下的 adb.exe AdbWinApi.dll AdbWinUsbApi.dll 复制并替换模拟器安装目录下的同名文件。

Scrcpy文件替换

2.3 真机连接 (WiFi ADB)

🅰️ 方案 A:已 Root 设备 (推荐,永久有效)

方法 1:使用 Magisk 模块 (最稳)
刷入模块后重启即可自动开启 WiFi ADB。

方法 2:修改 build.prop (硬核)

  1. 解锁 System 分区:下载 Syslock (v2.0.4) (需重启两次生效)
    Syslock解锁
  2. 修改文件:使用 RE管理器 编辑 /system/build.prop
    RE管理器编辑
  3. 添加代码:在文件末尾添加以下两行并重启:
    service.adb.tcp.port=5555
    persist.service.adb.enable=1
    

🅱️ 方案 B:未 Root 设备

需要 USB 连接一次电脑开启端口(重启手机后失效)。

adb tcpip 5555
# 断开USB后连接
adb connect 192.168.x.x:5555

注意:首次连接请务必勾选“一律允许使用这台计算机进行调试”。

允许调试

 

2.4. 模拟器连接的特殊处理
文章1只提到了推荐 Scrcpy,但在使用 雷电/逍遥模拟器 时,经常会出现连接不稳定的情况。

  • 解决方案: 必须进行文件替换。将 Scrcpy 或 SDK 目录下的 adb.exeAdbWinApi.dllAdbWinUsbApi.dll 三个文件,复制并强制替换到模拟器的安装目录中(通常在 bin 文件夹下),确保模拟器和脚本使用的 ADB 版本完全一致。

2.5. Fastboot 模式连接死循环 (Press any key to shutdown)


在小米设备线刷或救砖进入 Fastboot 时,如果电脑无法识别且手机左上角显示 press any key to shutdown

  • 解决方案: 这是 USB 3.0 兼容性问题。
    1. 尝试更换 USB 2.0 端口或使用 USB 集线器(Hub)。
    2. 注册表修复法(终极方案):
      新建一个 .bat 文件,粘贴以下内容并以管理员身份运行,然后重新连接手机:
      @echo off
      reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\18D1D00D0100" /v "osvc" /t REG_BINARY /d "0000" /f
      reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\18D1D00D0100" /v "SkipContainerIdQuery" /t REG_BINARY /d "01000000" /f
      reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\18D1D00D0100" /v "SkipBOSDescriptorQuery" /t REG_BINARY /d "01000000" /f
      pause
      

2.6. 固定 IP 以保证自动化稳定

  • 操作: 小米手机连接 WiFi 时,在设置中将隐私改为**“使用设备 MAC”**(非随机 MAC),并在路由器后台绑定 IP 与 MAC 地址,防止断连重连后 IP 变动导致 d = u2.connect(ip) 失效。

🔍 第三章:元素定位与 Weditor

启动 Weditor 进行元素抓取:

python -m weditor

浏览器将自动打开:http://atx.open.netease.com

Weditor界面

如果遇到 Android 11+ 截图黑屏或报错:
请参考下文 第6.2节 的解决方案。


💻 第四章:自动化脚本编写指南

4.1 常用操作速查

import uiautomator2 as u2
d = u2.connect(餘.168.31.109:5555')

# --- 点击与输入 ---
d(text="设置").click()
d(text="搜索").set_text("你好")
d(text="设置").long_click() # 长按

# --- 等待元素 ---
d(text="设置").wait(timeout=10.0)

# --- 特殊按键 ---
d.press("home")
d.press("back")
d.open_notification() # 下拉通知栏

# --- 获取信息 ---
xml = d.dump_hierarchy() # 获取页面 XML
info = d(text="设置").info # 获取元素属性

4.2 高级定位技巧

text 无法定位时,可以使用 XPath 或级联定位。

# 1. XPath 定位
d.xpath('//*[@text="领淘金币"]').click()

# 2. 兄弟节点定位 (例如:点击"WiFi"右边的开关)
d(text="Wi‑Fi").right(className="android.widget.Switch").click()

# 3. 子节点定位
d(className="ListView").child(text="Bluetooth").click()

# 4. 模糊匹配
d(textContains="安装").click()

1. 图案解锁 (九宫格) 实现
针对支付宝或系统锁屏的 Z 字形图案解锁逻辑:

def unlock_pattern(d):
    # 九宫格坐标点映射 (根据屏幕比例调整)
    # 假设 1-9 代表九宫格的位置
    xy = {
        1: (0.242 0.337) 2: (0.496 0.336) 3: (0.756 0.331)
        4: (0.238 0.449) 5: (0.516 0.447) 6: (0.752 0.446)
        7: (0.244 0.568) 8: (0.502 0.567) 9: (0.744 0.568)
    }
    # 解锁顺序:1->2->3->5->7->8->9 (Z字形)
    path = [xy[i] for i in [1 2 3 5 7 8 9]]
    d.swipe_points(path 0.2)

2. 深度 Toast 消息获取
文章1仅提到了基础获取,API 其实支持更多参数用于断言:

# 参数1: 等待超时时间(秒)
# 参数2: 缓存时间(秒),如果最近10秒内出现过该Toast则直接返回
# 参数3: 默认值,如果没有抓到Toast返回的内容
msg = d.toast.get_message(5.0 10.0 "default text")
assert "登录成功" in msg
# 清空缓存
d.toast.reset()

3. 常用 KeyCode 键值速查
除了 homeback,以下键值在处理特殊弹窗时非常有用:

  • 3 (HOME)
  • 4 (BACK)
  • 26 (POWER):电源键
  • 187 (APP_SWITCH):切换应用/最近任务
  • 66 (ENTER):回车
  • 67 (DEL):退格删除

4. 快速跳转 App 指定页面 (Activity)
很多时候 app_start 只能启动首页。如果想直接跳转到“签到页”,需要结合 ADB 命令:

  1. 获取当前页面 Activity: 手动进入目标页面,执行:
    adb shell dumpsys window | findstr mCurrentFocus
  2. 代码跳转:
    # 示例:直接跳到拼多多某活动页
    d.shell("am start -n com.xunmeng.pinduoduo/.share.system.GalleryShareActivity")
    

5. 暴力剪贴板方案 (Clipper)
如果 ATX 自带的 set_clipboard 失效,可安装 Clipper 应用,通过广播强制写入:

# 写入剪贴板
d.shell('am broadcast -a clipper.set -e text "需要复制的内容"')
# 读取剪贴板
output = d.shell('am broadcast -a clipper.get')

 


⚡ 第五章:Magisk Root 刷机全攻略

想要玩转安卓自动化,Root 权限几乎是必须的。以下资源已修复链接。

5.1 资源下载中心

  • 🔥 Magisk 官方发布页: GitHub Releases
  • 🔄 Magisk 国内更新源: http://www.aialbb.com/root.json
  • 📂 ROM 下载 (小米): XiaomiROM.com

5.2 刷入方法大全

方法一:一键刷入 TWRP (需电脑)

  • ☁️ 一键刷入工具包: 天翼云下载 (无需提取码)
    1. 手机进入 Fastboot 模式 (音量下+电源)。
    2. 运行工具一键刷入 TWRP。
    3. 在 TWRP 中 关闭 AVB2.0 校验,然后刷入 Magisk.zip。

方法二:修补 Boot 镜像 (通用推荐,无 REC 机型)

适用于红米 Note 10/11/12 等新机型。

  1. 提取 Boot: 下载同版本的刷机包,解压提取 boot.img。如果是 Payload.bin 格式,使用工具解包。
  2. 修补: 手机安装 Magisk App → 选择“修补文件” → 选中 boot.img → 导出 magisk_patched.img
  3. 刷入: 电脑连接手机进入 Fastboot。
    fastboot flash boot magisk_patched.img
    fastboot reboot
    

    (注:联发科机型可能需要先刷 vbmeta: fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img)

    重启手机

    fastboot reboot
    

     

5.3 隐藏 Root (过银行/游戏检测)

Android 8.1+ 推荐使用 Shamiko 模块。

  • 🔗 LSPosed (Zygisk): GitHub Releases
  • ☁️ Shamiko 模块: 天翼云下载 (访问码:q7bv)
    • 操作步骤:Magisk 设置开启 Zygisk → 安装 Shamiko → 关闭“遵守排除列表” → 在“配置排除列表”中勾选要隐藏 Root 的 APP。

 

5.4. Payload.bin 解包 (针对新版 ROM)


现在很多小米 ROM 包下载后没有 boot.img,只有一个 payload.bin 文件。

  • 工具: 下载 payload-dumper-go
  • 操作:payload.bin 拖拽到 payload-dumper-go.exe 上,工具会自动解包提取出 boot.img,然后再用 Magisk 修补。

5.5. 联发科 (MediaTek) 机型防无限重启


文章1提到了 vbmeta,这里给出详细指令。联发科机型刷入 Root 后,必须关闭验证,否则会无限重启:

# 刷入 vbmeta 镜像并关闭验证
fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img

 

5.6. Magisk 自定义更新源


如果 Magisk 无法联网更新,可设置自定义国内源:

  • URL: http://www.aialbb.com/root.json
  • 路径: Magisk 设置 -> 更新通道 -> 自定义。

 


🛠️ 第六章:疑难杂症与高级技巧

6.1 ATX-Agent 无法启动

如果连接后无反应,尝试手动启动守护进程:

adb shell
chmod 755 /data/local/tmp/atx-agent
/data/local/tmp/atx-agent server -d

6.2 安卓 11+ Weditor 截图修复

Weditor 自带截图功能在安卓 11+ 上可能黑屏。需修改 uiautomator2 源码,改用 ADB 原生截图。

6.3 解决 Flag Secure 黑屏 (登录/支付页黑屏)

安卓 12+ 限制了安全页面的录屏/截图。需刷入 Magisk 模块解除限制。

  • 🔗 Disable Flag Secure (XDA): 论坛原贴
  • ☁️ Disable Flag Secure (天翼云): 点击下载 (访问码:hu7z) (安装较慢,请耐心等待)

6.4 剪贴板操作 (输入复杂文本)

  • 方法一 (ATX): d.set_clipboard("text" 'label')
  • 方法二 (Clipper): 使用广播命令 (需安装 Clipper APK)。
    • 🔗 Clipper APK: GitHub 项目
    • 命令:adb shell am broadcast -a clipper.set -e text "内容"

6.5 公网远程连接 ADB

端口转发

  • 内网穿透:推荐使用 FRP 模块进行映射。
  • 连接命令adb connect 域名:端口

6.6 H5 / WebView 自动化

6.7 弹窗监控 (WatchContext)

自动处理广告或权限弹窗:

with d.watch_context() as ctx:
    ctx.when("立即更新").click()
    ctx.when("跳过").click()
    ctx.wait_stable()

 6.8.解决一些应用app_start无法启动:

 一、打开应用后先用

以拼多多为例

adb shell dumpsys window | findstr mCurrentFocus

mCurrentFocus=Window{46411ab mode=0 rootTaskId=97632 u0 com.xunmeng.pinduoduo/com.xunmeng.pinduoduo.ui.activity.HomeActivity}

命令找到【当前连接电脑的手机正在运行的APP】的包名

可以用正则匹配

import os
import re
activity_string = os.popen('adb -s 192.168.31.161:5555 shell dumpsys package com.lxcm.taocoupon  | findstr \/ |findstr filter').read()
# print(ret)

pattern = r"/(.*?) filter"  # 匹配斜杠和"filter"之间的文字

matches = re.findall(pattern, activity_string, re.MULTILINE)
activity_names = [match.strip() for match in matches]
activity_list = []
for activity_name in activity_names:
    # print(activity_name)
    activity_list.append(activity_name)
print(activity_list)

 

 

二、再用

包名= com.xunmeng.pinduoduo

adb shell dumpsys package 包名  | findstr \/ |findstr filter
  • adb shell dumpsys package com.xunmeng.pinduoduo  | findstr \/ |findstr filter

会发现很多Activit
命令找到合适的入口Activity。

最终找到拼多多为.share.system.GalleryShareActivit

三、使用

adb shell am start com.xxx.xxx/xxx.xxx.xxx.xxx
  • adb shell am start -n com.xunmeng.pinduoduo/.share.system.GalleryShareActivity

python 获取方法

windows

import os
import re
import time
import uiautomator2 as u2

print("获取能运行的activity,获取到安装安装包名字,先回到桌面,再运行")
packege_name = 'alook.browser'
ip = '192.168.31.161'

d = u2.connect(ip)
# 写入不想遍历的activity
# '.FileIntentReceiverActivity', '.IntentReceiverActivity','.TranslateIntentReceiverActivity', '.LauncherActivity'
dis_contain = []

act_list = []
name = os.popen('adb  -s %s shell dumpsys package %s  | findstr \/ |findstr filter' % (ip, packege_name)).read()


for i in name.split('\n'):
    r_lis = re.compile('/(.*?) ', re.S).findall(i)
    if r_lis:
        activity = r_lis[0]
        if activity in dis_contain or activity in act_list:
            continue
        print(activity)

        d.app_start(packege_name, activity)
        time.sleep(1)

        text = os.popen('adb  -s %s shell dumpsys window | findstr mCurrentFocus' % ip).read()
        act_list.append(activity)

        if packege_name in text:
            print('满足不在桌面的:activity=', activity)
            console = input("是否继续,是的话回到桌面输入(y)继续,否的话输入(n)停止:")
            console = console.strip()
            if console == 'y':
                d.app_stop(packege_name)
                time.sleep(1)
                d.press('home')
                continue
            else:
                break

print('--' * 100)
print('加入dis_contain的act_list', act_list)

linux

import os
import re
import time
import uiautomator2 as u2

print("获取能运行的activity,获取到安装安装包名字,先回到桌面,再运行")
packege_name = 'com.dragon.read'
ip = '192.168.31.182'

d = u2.connect(ip)
# 写入不想遍历的activity
# '.FileIntentReceiverActivity', '.IntentReceiverActivity','.TranslateIntentReceiverActivity', '.LauncherActivity'
dis_contain = []

act_list = []
name = os.popen('adb  -s %s shell dumpsys package %s  | grep "/" | grep "filter"' % (ip, packege_name)).read()


for i in name.split('\n'):
    r_lis = re.compile('/(.*?) ', re.S).findall(i)
    if r_lis:
        activity = r_lis[0]
        if activity in dis_contain or activity in act_list:
            continue
        print(activity)

        d.app_start(packege_name, activity)
        time.sleep(1)

        text = os.popen('adb  -s %s shell dumpsys window | grep mCurrentFocus' % ip).read()
        act_list.append(activity)

        if packege_name in text:
            print('满足不在桌面的:activity=', activity)
            console = input("是否继续,是的话回到桌面输入(y)继续,否的话输入(n)停止:")
            console = console.strip()
            if console == 'y':
                d.app_stop(packege_name)
                time.sleep(1)
                d.press('home')
                continue
            else:
                break

print('--' * 100)
print('加入dis_contain的act_list', act_list)

 

6.9. 报错 Invalid version

  • 现象: 运行脚本时提示版本无效。
  • 原因: packaging 库版本过高导致不兼容。
  • 解决: 降级库版本:
    pip install packaging==21.3

6.10. 报错 SecurityException: Injecting to another application...

  • 现象: 无法点击或操作屏幕。
  • 原因: 小米手机未开启“USB 调试(安全设置)”。
  • 解决: 必须插卡登录小米账号,在开发者选项中开启**“USB 调试(安全设置)”**(允许模拟点击)。

6.11. Android 11+ Weditor/截图 黑屏修复 (Python 代码版)


如果无法修改源码,可以在代码中重写截图函数,强制使用 ADB 截图绕过黑屏:

import io
from PIL import Image

def adb_screenshot(d):
    # 使用 adb exec-out 直接获取二进制流,速度快且兼容性好
    raw = d.shell("screencap -p" stream=True).raw
    # 注意:部分系统 screencap 输出可能包含 \r\n 转换问题,需根据实际情况处理
    return Image.open(raw)

# 使用方式
img = adb_screenshot(d)
img.save("screenshot.jpg")

6.12. 距离感应器阻挡操作

  • 现象: 脚本运行时屏幕提示“请勿遮挡听筒区域”。
  • 解决: 除了关闭防误触模式外,还需要在设置中关闭“距离感应器”(部分机型在电话设置或锁屏设置中)。

6.13. 解决 ADB 安装 APK 提示 INSTALL_FAILED_TEST_ONLY 问题

一问题现象

执行常规 ADB 安装命令:

adb -s 设备地址 install "APK文件路径"

出现报错:

Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]

无法正常安装 APK。

二核心原因

该 APK 为测试/调试编译版本,Android 系统默认禁止普通 adb install 命令安装此类文件。

三解决办法(按优先级排序)

方案 1:添加 -t 参数(最简便,优先使用)

直接在 install 后添加 -t 参数,允许安装测试版 APK,修改命令如下(复用你的设备信息和文件路径):

adb -s 192.168.31.49:35615 install -t "C:\迅雷下载\myaccessibility1.0.45.apk"

执行后即可完成安装。

方案 2:手动拷贝(备选,绕开 ADB 安装限制)

  1. adb push 将 APK 拷贝到手机存储:
    adb -s 192.168.31.49:35615 push "C:\迅雷下载\myaccessibility1.0.45.apk" /sdcard/Download/
    
  2. 手机端打开「文件管理器」,找到 Download 文件夹中的 APK,点击安装(开启「允许安装未知来源应用」即可)。

四补充注意事项

  1. 确保手机已开启「USB 调试」,否则 ADB 无法连接设备。
  2. 若仍安装失败,检查 APK 是否损坏(重新下载)或手机存储空间是否充足。
  3. 无需 ROOT 手机,以上方法均可直接使用。

 

6.14 Android UiAutomation 空指针异常与“假死”僵尸进程的自愈实践

Android UiAutomation 空指针异常与“假死”僵尸进程的自愈实践

6.15 每次开启无线调试自动重启 终极修复教程
红米 Note10 Pro MIUI14.0.6.0 无线调试重启 终极修复教程


⚙️ 第七章:小米手机专属深度设置

7.1 彻底关闭小米 USB 安装弹窗

此步骤最为关键,否则无法静默安装 ATX 守护程序。

  1. 开启入口:在开发者选项中开启“MIUI 优化”(为了显示设置入口,设置完可关回)。
  2. 设置权限设置应用设置授权管理 → 右上角设置图标 → 关闭 [USB 安装管理]
  3. 关闭监控:同页面关闭 [应用权限监控]
  4. 重启手机

7.2 线刷救砖工具

如果刷机失败卡 Logo,使用官方工具救砖。


📱 第八章:常用 ADB 指令速查

修改分辨率与 DPI (适配脚本):

adb shell wm size 1080x2400  # 修改分辨率
adb shell wm density 480     # 修改DPI
adb shell wm size reset      # 恢复默认

获取设备信息:

adb shell getprop ro.product.model  # 型号
adb shell getprop ro.build.version.release # 安卓版本
adb shell cat /sys/class/net/wlan0/address # MAC地址

📝 版权声明:本文基于原作者经验总结优化,完整保留了技术路径与资源链接。文中涉及的云盘资源如有失效,建议通过 GitHub 项目主页获取最新版本。刷机有风险,操作需谨慎!