10

We are setting up a continuous integration server for our Android development and we've quickly run into ADB's waiting for device issue.

For the record, we've already tried a lot of combinations of adb kill-server, adb start-server, adb devices, etc. to no avail.

Sadly, all I've found on the internet are variations of "unplug and replug the device", which is obviously not a solution for us (we can't spare a human being to sit by the CI server to unplug and replug devices before each build).

As a bit of background, we use Jenkins on a Mac, since it runs our CI for iOS too.

While approaching the problem I thought that if at the OS level the device is found, that's at least a start. Indeed, running a command like system_profiler SPUSBDataType successfully finds the device, including the serial number that ADB reports when working correctly.

I've attempted a few rather lame commands to "refresh" all USB activity, but I've gone nowhere. It's not that you can mount/unmount the device, but to be honest I'm not even sure where the problem is, I don't know enough about low level USB protocols, let alone for Macs. My lurking of the ADB source code was a very, very long shot.

So at this point I'm all ears for a solution that would allow us consistently running Android on our CI server. Be it a few commands before each Jenkins job, patching ADB or any other black magic trick.

6 Answers 6

9

Found a way of solving it, so posting here for completeness. Please note that I'm not saying this is the best way of solving it, but it's worked for us.

So, we realised the problem happened after long periods of CI inactivity (in the range of hours). So we created a simple script that calls adb devices every 10 seconds. And the problem is gone, no more "waiting for device" issues.

On Linux you can do this with a simple cron job and on OSX with launchctl and I'm sure there's a Windows equivalent.

Regardless, "pinging" the devices every 10 seconds solved it for us.

1
  • 1
    Thanks! Seems like I was having the same issue. Unplugging and plugging back the USB cable made the device show up in the list. Jun 6, 2014 at 19:16
5

Enabling USB debugging (Settings => Developer options) in the phone helped.

1

We had some similiar problems with our Continuous Integration environment with Android devices from an OSX machine (also using for both iOS and Android).

I believe the problem is that you are allowing Jenkins to start the adb server. The causes problems because Jenkins jobs are associated with shells that come in and out of existence. If Jenkins kicks off the adb daemon with an "adb devices" call (for example), then the adb daemon will be owned by some short-lived Jenkins shell, and when that shell finishes executing and closes, the adb daemon will be cleaned up, until it is started back up automatically by another adb call. This results in a cycle of starting and stopping the adb daemon, but what you want is for it to just stay up indefinitely.

One way to fix this, is to just run "adb devices" from a shell that gets left open on the CI machine. You can tell if it is the parent process by whether this message is shown after running

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

This is an annoying step to have to perform every time your machine restarts, and if anyone closes that command window you will revert to the previous problem.

In theory, a better way would be to make .plist file to trigger the adb daemon on bootup. Here's an example: ~/Library/LaunchAgents/server.adb.plist. This basically just runs adb start-server from the user launch daemon to avoid Jenkins from owning it.

<?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>

The problem with this, however, is that it just starts adb, but it doesn't block, so you can't use the KeepAlive launch control functionality. Also, it doesn't seem to work for the desired purpose. If anyone knows of a way to run adb in "daemon" mode, so it doesn't return, then this launchctl mechanism could be set up to automatically restart it if it dies, therefore ensuring that Jenkins doesn't ever get ownership. Oh well, for now I'll just be running "adb devices" in a shell window and leaving it open.

1

I solved this by using a programmable power strip to reboot the usb hubs prior to each test run. This did the same as unplugging and plugging the usb cables back in.

1
  • Can you expalin more ?
    – DVG
    Aug 3, 2017 at 12:11
1

I just wanted to follow up on the excellent suggestion by juan-delgado. I found on MacOS High Sierra that running adb every 10 seconds with the watch command was also effective as a quick workaround:

watch -n 10 adb -d devices

This allows me to sidestep creating a .plist file, but the obvious drawback is it's not a permanent solution. The watch command is available on previous versions of OSX, so it should be effective there as well.

1
  • I didn't have watch on macOS Catalina, but was able to install it easily with brew install watch.
    – mokagio
    Apr 23, 2020 at 2:59
-1

Solved here by changing USB cable.

There are different sub-standards of USB, some cables are just for charging; sometimes they may be just broken.

2
  • Could you please be more detailed? Sep 18, 2017 at 19:08
  • Thanks for the info! Yea let me just go ahead and buy that USB cable! Thank you soo much!
    – smac89
    Jan 20, 2021 at 7:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .