Introduction
If you have
been debugging some Android apps on an HTC phone, you have probably noticed the
annoying message that is shown when you try to debug a phone over USB on a
computer running HTC Sync:
adb server is out of date. killing...
* daemon started successfully *
The message
is usually accompanied by 3-5 seconds of waiting time and can appear several
times before you manage to start debugging. The worst thing is that sometimes
it does not manage to restart the daemon
and aborts the launching after 10-20 seconds of waiting with a message like that:
adb server is out of date. killing...
* daemon started successfully *
** daemon still not runningerror: cannot connect to daemon
Although the problem seems almost random, there is a simple explanation to it and a clean way of fixing it.
The ADB Server
ADB stands
for Android Debug Bridge. It is a tool that is used by Android environment to
do a variety of tasks: list connected devices, transfer files between them,
establish TCP/IP connections… The last feature is directly used by the HTC Sync
application to communicate with the phone over USB.
Let’s now
see what exactly happens when you connect your phone and try to debug it.
- HTC Sync (more specifically, htcUPCTLoader.exe continuously running in the background)
detects that you have connected a device and tries to forward a TCP/IP port to
it. To do so, it runs the adb.exe from its own folder and tells it to start
mapping the port. The adb.exe keeps on running in the background providing the
port map for HTC Sync.
- When you start debugging with the Android
SDK, it does several minor jobs (e.g. lists devices, deploys your App, etc)
each involving a call to its own adb.exe. When this happens, the newer adb.exe
detects that the older adb.exe from HTC Sync is running and terminates it, then
it runs its own instance.
- The HTC Sync running in the
background detects that the port mapping has been broken and tries to restart
it. What happens then? Right, adb.exe from Android SDK gets kicked off. If this
happens before the adb.exe from SDK manages to complete, you get an error
message and your debugging fails.
The Solution
First of
all, we need to find the old instance of adb.exe that interferes with Android
SDK. This can be done by opening Task Manager, finding adb.exe there and
selecting “Properties”. Do not forget to connect your phone to USB before doing
that.
A trivial
solution then would be to delete/rename the adb.exe used by HTC Sync. However,
this would break HTC Sync.
Another one
is to kill or suspend htcUPCTLoader.exe for the time you are debugging your app.
This will prevent it from interfering with the adb.exe from the Android SDK.
Finally,
you can make a simple stub that reads the location of the real ADB.exe from the Registry and runs it with the original command line:
#include "stdafx.h"
#include <bzscore/Win32/registry.h>
using namespace BazisLib;
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t *p = GetCommandLineW();
if (p[0] == '\"')
p = wcschr(p+1,'\"');
else
p = wcschr(p, ' ');
if (!p)
p = L"";
else
p+=2;
wchar_t *pwsz = new wchar_t[512 + wcslen(p)];
String ADBPath = RegistryKey(HKEY_CURRENT_USER,
L"SOFTWARE\\Sysprogs\\ADBFix", 0, false)[L"SDKPath"];
if (ADBPath.empty())
ADBPath = L"adb_noadbfix.exe";
else
ADBPath += L"\\platform-tools\\adb.exe";
swprintf(pwsz, L"\"%s\" %s", ADBPath.c_str(), p);
STARTUPINFO info = {sizeof(info), };
PROCESS_INFORMATION PI;
CreateProcess(0, pwsz, 0, 0, 0, 0, 0, 0, &info, &PI);
WaitForSingleObject(PI.hProcess, INFINITE);
DWORD exitCode = -1;
GetExitCodeProcess(PI.hProcess, &exitCode);
return exitCode;
}
You can rename the adb.exe in the HTC Sync directory to adb_noadbfix.exe and put the stub instead of the original file.
You can get the binary version of the stub here along with a simple installer GUI: