摘要:本文是针对安卓自动化测试(特别是小米设备)的深度实战总结。涵盖环境配置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 手机,以上方法均可直接使用。

 


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

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 项目主页获取最新版本。刷机有风险,操作需谨慎!