解决 ADB“等待设备”问题

解决 ADB“等待设备”问题

我们正在为我们的 Android 开发设置一个持续集成服务器,并且我们很快就遇到了 ADB正在等待设备问题。

需要说明的是,我们已经尝试了很多种组合,包括adb kill-server、、adb start-serveradb devices,但都无济于事。

可悲的是,我在互联网上找到的都是“拔下并重新插入设备”的变体,这显然不是我们的解决方案(我们无法让一个人坐在 CI 服务器旁边在每次构建之前拔下并重新插入设备)。

背景介绍一下,我们在 Mac 上使用 Jenkins,因为它也运行我们的 iOS CI。

在处理这个问题时,我认为如果在操作系统级别找到了设备,那至少是一个开始。事实上,运行类似这样的命令可以system_profiler SPUSBDataType成功找到设备,包括 ADB 在正常工作时报告的序列号。

我尝试了一些相当蹩脚的命令来“刷新”所有 USB 活动,但毫无进展。这并不是说你可以安装/卸载设备,但说实话,我甚至不确定问题出在哪里,我对低级 USB 协议了解不够,更不用说 Mac 了。我潜伏在ADB 源代码是一个非常非常渺茫的机会。

因此,现在我非常希望找到一个解决方案,让我们能够在 CI 服务器上持续运行 Android。无论是在每次 Jenkins 作业之前执行几个命令、修补 ADB 还是任何其他黑魔法。

答案1

找到了解决方法,因此为了完整起见,在此发布。请注意,我并不是说这是最好的解决方法,但是对我们来说很有效。

因此,我们意识到问题发生在 CI 长时间不活动(数小时范围内)之后。所以我们创建了一个adb devices每 10 秒调用一次的简单脚本。问题就解决了,不再有“等待设备”问题。

在 Linux 上,您可以通过一个简单的cron作业来完成此操作,在 OSX 上launchctl,我相信 Windows 上也有一个等效操作。

无论如何,每 10 秒“ping”一次设备就可以为我们解决这个问题。

答案2

在手机中启用 USB 调试(设置 => 开发者选项)有帮助。

答案3

我们在 OSX 机器(也用于 iOS 和 Android)上的 Android 设备的持续集成环境中也遇到了一些类似的问题。

我认为问题在于您允许 Jenkins 启动 adb 服务器。这会导致问题,因为 Jenkins 作业与出现和消失的 shell 相关联。如果 Jenkins 使用“adb devices”调用启动 adb 守护进程(例如),则 adb 守护进程将由某个短暂的 Jenkins shell 拥有,并且当该 shell 完成执行并关闭时,adb 守护进程将被清理,直到它被另一个 adb 调用自动重新启动。这会导致启动和停止 adb 守护进程的循环,但您想要的是让它无限期地保持运行。

解决此问题的一种方法是从 CI 机器上打开的 shell 运行“adb devices”。您可以通过运行后是否显示此消息来判断它是否是父进程

blah$ adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached
xxxxxxxxxxx          device

每次机器重新启动时都必须执行这个烦人的步骤,如果有人关闭该命令窗口,您将回到之前的问题。

理论上,更好的方法是制作 .plist 文件以在启动时触发 adb 守护程序。以下是示例:~/Library/LaunchAgents/server.adb.plist。这基本上只是从用户启动守护程序运行 adb start-server,以避免 Jenkins 拥有它。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>server.adb</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/Shared/Jenkins/android-sdk/platform-tools/adb</string>
        <string>start-server</string>
    </array>
  </dict>
</plist>

但是,这样做的问题是,它只是启动了 adb,但没有阻止,因此您无法使用 KeepAlive 启动控制功能。此外,它似乎无法达到预期目的。如果有人知道以“守护进程”模式运行 adb 的方法,这样它就不会返回,那么可以设置此 launchctl 机制,以便在它死机时自动重新启动它,从而确保 Jenkins 永远不会获得所有权。哦,好吧,现在我只是在 shell 窗口中运行“adb devices”并将其保持打开状态。

答案4

我只是想跟进胡安·德尔加多。我发现在 MacOS High Sierra 上,adb每 10 秒运行一次该watch命令也是一种有效的快速解决方法:

watch -n 10 adb -d devices

这样我就不用创建.plist文件了,但明显的缺点是这不是一个永久的解决方案。该watch命令在以前的 OSX 版本中可用,因此它应该在那里也有效。

相关内容