Use ADB in Remote Machine

Some times we develop Android on a remote Linux machine (or WSL). We need to use adb in remote machine and connect to the local Android device.
Android Debug Bridge (adb)  |  Android Studio  |  Android Developers

Just to be more clear:

  • The “local machine” means the machine you are using directly and you will also connect the Android device to the “local machine” directly through USB. It can be Windows host machine with a WSL inside it, it can also be a Linux / Mac.
  • The “remote machine” means the Linux machine you store the project code and use it to build and debug. Normally it is WSL (Ubuntu) or a remote Ubuntu machine. This machine can not connect the Android device directly, so that is why we need to do the whole stuff in this doc.

Here is how we can achieve this:

  1. Connect physical devices to / run emulators on local machine.
  2. Run adb in nodaemon server mode on local machine.
  3. Create a TCP port forwarding from local machine to remove machine using socat (or ssh).
  4. Use adb in remote to connect local devices.

image-20210812153212102

Prepare the Environment

Install ADB Using Android Studio

Install ADB on both local and remote machine.

ADB is included in the Android SDK platform tools. It is recommended to install Android Studio directly and it will help you download Android SDK:

  • Install latest Android Studio on both local and remote machine.
  • Start Android Studio and follow the guide, the Android SDK will be automatically downloaded and installed.
  • Search “Android SDK” in the settings to see the Android SDK Location and the Platform-Tools (including adb) version. Make sure the version in both local and remote are the same.
  • Add platform-tools directory to your PATH environment. e.g. /home/jzj/Android/Sdk/platform-tools.

Install ADB Manually

If you wants to download and install ADB manually, please make sure:

  • ADB in local machine and remote machine are the same version.
  • On remote machine, ADB in command line and Android Studio are the same one.

Download platform tools only from here:
SDK Platform Tools release notes  |  Android Studio  |  Android Developers

Check adb version in command line:

1
2
3
4
5
6
7
8
9
# show adb path
$ which adb
/home/xxx/Android/Sdk/platform-tools/adb

# show adb version
$ adb version
Android Debug Bridge version 1.0.41
Version 31.0.2-7242960
Installed as /home/xxx/Android/sdk/platform-tools/adb

(Windows Only) Configure Firewall for ADB

On Windows, we need to enable ADB network access in firewall settings.

3. (WSL Only) Install socat

For WSL, install socat first. It is used to do the port forwarding.

1
sudo apt update && sudo apt install -y socat

Start the Environment Automatically for WSL

We have a script to start the adb environment automatically. If it is not working, try to run it step by step to see what is going wrong.

Usage:

  1. Install adb on Windows and change $WSL_HOST_ADB to the adb location following the example format. In WSL, /mnt/d is point to the D: drive in Windows.
  2. Install adb on WSL. Make sure you are using the same adb in terminal and Android Studio. And make sure you installed the same version of adb in Windows and WSL.
  3. Add the following content to your WSL ~/.bashrc and run source ~/.bashrc to refresh.
  4. Run startWslAdb / stopWslAdb to start/stop adb environment.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# adb path on windows
WSL_HOST_ADB='/mnt/d/AndroidSdk/platform-tools/adb.exe'
# export variable to set adb port for wsl
export ANDROID_ADB_SERVER_PORT=5038

startWslAdb() {
if ! [ -x "$(command -v socat)" ]; then
echo 'Please install socat first:' >&2
echo 'sudo apt update && sudo apt install -y socat'
return 1
fi

stopWslAdb

echo '>>>> Check adb devices on windows <<<<'
$WSL_HOST_ADB devices
sleep 1
$WSL_HOST_ADB kill-server
sleep 1

echo '>>>> Start adb on windows in server mode <<<<'
nohup $WSL_HOST_ADB -a nodaemon server start >/dev/null 2>&1 &
echo

# get windows host ip address
# https://learn.microsoft.com/en-us/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip
# local HOST_IP=$(cat /etc/resolv.conf | tail -n1 | cut -d " " -f 2)
local HOST_IP=`ip route show | grep -i default | awk '{ print $3}'`

echo ">>>> Forward localhost:$ANDROID_ADB_SERVER_PORT to ${HOST_IP}:5037 <<<<"
nohup socat TCP-LISTEN:$ANDROID_ADB_SERVER_PORT,reuseaddr,fork TCP:${HOST_IP}:5037 >/dev/null 2>&1 &
sleep 1
echo

echo '>>>> Get adb devices <<<<'
adb devices
}

stopWslAdb() {
echo '>>>> Kill running processes <<<<'
pkill -9 socat

$WSL_HOST_ADB kill-server >/dev/null 2>&1
adb kill-server >/dev/null 2>&1

pkill -9 adb.exe
pkill -9 adb
sleep 1
echo
}

Start the Environment Automatically for Remote Linux Machine

Usage

  1. Setup ssh key for remote machine.
  2. Install adb on local machine.
  3. Install adb on remote machine and change REMOTE_ADB_PATH value to the adb location. Make sure you are using the same adb in terminal and Android Studio. And make sure you installed the same version of adb in local and remote machine.
  4. Add the following content to your local ~/.bashrc and run source ~/.bashrc to refresh.
  5. Run startRemoteAdb USER HOST / stopRemoteAdb USER HOST to start/stop adb environment.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
REMOTE_ADB_PATH='$HOME/Android/Sdk/platform-tools/adb'
REMOTE_ADB_PORT=5037

_remoteCmd() {
local USER=$1
local HOST=$2
ssh $USER@$HOST $3
}

_remoteAdb() {
local USER=$1
local HOST=$2
_remoteCmd $USER $HOST "$REMOTE_ADB_PATH $3"
}

startRemoteAdb() {
if [ $# -ne 2 ]; then
echo 'Usage: startRemoteAdb USER HOST'
echo 'Example: startRemoteAdb jzj 192.168.5.200'
return 1
fi

local USER=$1
local HOST=$2

# stop existing adb process
stopRemoteAdb $USER $HOST

echo '>>>> Check adb devices on local <<<<'
adb devices
sleep 1
adb kill-server
sleep 1

echo '>>>> Start adb on local in server mode <<<<'
nohup adb -a nodaemon server start >/dev/null 2>&1 &
echo

echo ">>>> Forward localhost:5037 to $HOST:$REMOTE_ADB_PORT <<<<"
ssh -R 5037:127.0.0.1:$REMOTE_ADB_PORT -f -N $USER@$HOST -o ServerAliveInterval=240
sleep 1
echo

echo '>>>> Remote get adb devices <<<<'
_remoteAdb $USER $HOST devices
}

stopRemoteAdb() {
local USER=$1
local HOST=$2

echo '>>>> Kill running processes <<<<'
# kill existing adb process
_remoteAdb $USER $HOST kill-server
adb kill-server
# kill ssh port forward command which contains 5037
ps -lef | grep ssh | grep 5037 | awk "{print \$2}" | xargs kill
sleep 1
echo
}

Troubleshooting

Check Installed ADB

  • Please make sure the WSL Windows host machine (or local Linux machine) and the WSL (or remote Linux machine) are using the same version of adb. Otherwise they may not be able to connect and work together.
  • Please make sure the adb in the command line and the adb used by Android Studio in WSL (or remote Linux machine) is the same executable file. Otherwise Android Studio will try to start the adb which the command line already starts another adb which will cause a conflict.

Restart Your Machine

Try to restart your machine may also help. Adb will start a server, sometimes the TCP port may be occupied for some reason, so restarting the machine may help.

Run The Script Step by Step

Try to run the automatic script step by step to see what is going wrong.

Adb Forwarding Stop Works Every Time Android Studio Exits

If your adb forwarding stop works every time Android Studio exits, you should:

  1. Change Android Studio settings to use existing adb server
  2. Use environment variable to set the adb port in remote machine to the same value in Android Studio (in the screenshot the value is 5038)
  3. Change the corresponding port in the script.
1
2
# this should be added to the "remote machine"
export ANDROID_ADB_SERVER_PORT=5038

ADB Install APK is Very Slow In WSL

If ADB install APK is very slow in WSL, try running this in Windows Power Shell with administrator permission:

1
2
3
4
5
6
7
# run this to get all the network adapters, find the name of the virtual adapter for WSL, the name will be like `vEthernet (WSL)` or `vEthernet (WSL (Hyper-V firewall))`
Get-NetAdapter -IncludeHidden | Format-List -Property "Name"

# replace the name to the name on your machine
Disable-NetAdapterBinding -Name "vEthernet (WSL)" -ComponentID ms_tcpip6 -IncludeHidden
Disable-NetAdapterLso -IncludeHidden -Name "vEthernet (WSL)"
Restart-NetAdapter -Name "vEthernet (WSL)" -IncludeHidden

Very slow network speeds · Issue #8171 · microsoft/WSL · GitHub
Get-NetAdapter (NetAdapter) | Microsoft Learn