Connecting to a USB Android device in a Docker container via ADB - android

I have created a Docker image which contains the Android SDK and am trying to expose my Android phone in a container running this image. So I used the --privileged flag and mounted the USB devices as follows:
$ docker run --privileged -v /dev/bus/usb:/dev/bus/usb -d -P my-android:0.0.1
However, when I run ADB devices, it does not show me the USB device:
ubuntu#d56b666be455:~/Android/Sdk/platform-tools$ ./adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached
ubuntu#d56b666be455:~/Android/Sdk/platform-tools$
lsusb inside the container lists the device:
ubuntu#d56b666be455:~$ lsusb
...
Bus 002 Device 017: ID 04e8:6866 Samsung Electronics Co., Ltd GT-I9300 Phone [Galaxy S III] (debugging mode)
The device is however visible on the host:
⇒ ./adb devices
List of devices attached
4d11abcd65b74045 device
Host OS
$ uname -a
Linux ananya 3.16.0-33-generic #44~14.04.1-Ubuntu SMP Fri Mar 13 10:33:29 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Docker version
$ docker --version
Docker version 1.5.0, build a8a31ef
What could be the issue?

I don't think the ADB daemon running on the device can be connected to two ADB servers. Try disconnecting it from your host machine's ADB and then connect it to the Docker container's ADB.

While I was trying the same, I ran into some other problems related to that, which I would like to share so that others may save their time:
Problem 1: lsusb was not installed in the container
In my case lsusb was not installed, so I installed it with the below command:
apt-get update
apt-get install usbutils
Problem 2: not able to see the device even after lsusb and ADB SDK installation
You need to restart your container with the -v option, and yes don't forget to kill the ADB server as stated in one of the answers.
On the host:
adb-kill server
docker run -ti -d --privileged -v /dev/bus/usb:/dev/bus/usb container_name
In case someone wanted do it from scratch, I have written a blog post on it:
How to connect ADB devices to Linux container

This doesn't answer the exact question you were asking, but does address what you were trying to accomplish - connecting to an android device connected to a docker host from an adb client running inside a docker container. I'm including this for anyone trying to accomplish the same thing (like I was).
The adb client supports a -H option which tells it where to find the adb server to connect to. Docker supports the hostname "host.docker.internal" which always maps to the IP address of the docker host. Assuming your device is connected to the docker host, you can do the following to get your containerized adb client to connect to the adb server running on the docker host:
adb -H host.docker.internal devices
Accomplishes the goal without having to mount the USB ports.
Reference: https://developer.android.com/studio/command-line/adb
Update:
I recently learned that host.docker.internal is only supported on Docker for Mac in versions 18.0 and above.

Running with just --privileged -v /dev/bus/usb:/dev/bus/usb did not work for me.
I tried forwarding the adb daemon's listening port using -p 5037:5037, but that did not help either.
It worked only after I added --net host.
This means the host machine's net interfaces are exposed to the docker so use it if you are fine with that. Maybe there are more ports that needed to be forwarded other than 5037....

This works for me.
Set your devices in PPT mode
(optionaly) Check if the devices is available localy $ adb devices
I try with many options and only one works. Using --network flag as the next example
Run container
$ docker run -it --net host ubuntu bash
output:
List of devices attached
464e128 device
I used this Dockerfile. Is for flutter projects

Update:
I ended up using --privileged and -v to map the whole of /dev/bus/usb and patching adb to accept one environment variable to specify the root USB device tree - /dev/bus/usb/001 etc.
This allowed us to use different USB busses for different containers for different groups of the same phone, and another environment variable patch allowed different VID:PID lists for different types of phone.
We're trying to allocate different USB buses to different Docker containers running TeamCity clients.
Each container needs ANDROID_ADB_SERVER_PORT setting to a different port (because we're not using segregated networking).
The host machine can't run adbd, because only one adbd can talk to a phone at any given time.
Each container gets one of the /dev/bus/usb/xxx directories, so we can plug phones into particular containers.
We have to synchronise the /dev/bus/usb/xxx directory every few seconds, to allow hot-plugging and reboots - just a shell loop on the host that runs tar cf devxxx.tar /dev/bus/usb/xxx, docker cp to transfer it, then docker exec to untar inside the container's /tmp, diff to detect nodes to delete, and mv -n to move new nodes in.
In fact, because we're running on Linux, we can probably just set up udev scripts, per Howto run a script when a USB device is pluged in.

Excuse me for offtop. But I cannot answer to this question so I write it down here.
I am using ubuntu:18.04 and tried to connect my Samsung Galaxy A3 2016 and debug it with ADB. Devices was unauthorized and no dialog popped up on the screen!
How I solved the problem:
I was interested will the problem still occure inside a Docker container? The answer was "No!".
Inside a Docker container, that I invoked with following: (this is the answer for this topic :) )
docker run --name android-adb -it -d --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu:16.04 bash
I downloaded platform-tools (distribution with ADB). Added its path to environment. And restarted bash
After restarting ADB server inside Docker container AND killing ADB server on host machine. I found out that confirmation dialog appeared on the smartphone's screen!
So on the host machine the problem was in .android directory I think. Just move it to .android-backup. The next adb start-server command will create new one. Also I replaced platform-tools folder with most recent

Related

Android ADB: Device unauthorized trying to connect to a port-forwarded remote emulator

Background:
I recently upgraded to an AMD processor and found that the Android device emulator was complaining about not having hardware acceleration. (This is an issue for another question). My old Intel computer worked fine, so I decided to run the emulator on the old Intel PC (emu-pc) and use my new AMD computer (dev-pc) to code.
Problem:
I wasn't able to directly have the emulator expose its ports on the emu-pc to connect to via adb on the dev-pc (again an issue for another question), so I installed the Windows 10 OpenSSH server (Microsoft instructions) and connected to it from my dev-pc, forwarding the proper ADB ports:
ssh {you}#<{remote ip} -L 5554:localhost:5554 -L 5555:localhost:5555
I then tried connecting to the remote emulator via adb:
adb connect localhost
I was met with
$ ./adb devices
List of devices attached
localhost:5555 unauthorized
I've tried a few of the posts stating you should disable and re-enable USB debugging or revoke all the USB debugging authorization or use the "Wipe Data" option in the AVD Manager. None of these worked. I also tried messing with the adbkeys on the emulator under /data/misc/adb/adbkeys but I get permission denied trying to do anything to that file. (I also can't ls it via an adb shell)
Any ideas?
I found something that worked for me. I was able to telnet to the emu-pc via port 5554, where I tried to auth on the Android console. The login message said:
Android Console: type 'auth <auth_token>' to authenticate
Android Console: you can find your <auth_token> in
'C:\Users\exile57\.emulator_console_auth_token'
I found that file and was able to log in. This made me think that the emulator thinks the connection is coming from the emu-pc, yet the keys that I was using were generated on the dev-pc. I found the keys on emu-pc in C:\Users\[your user]\.android as adbkey and adbkey.pub. I copied those to the dev-pc, killed the adb server, disconnected all devices, then tried reconnecting:
$ ./adb disconnect
./adb kill-server
./adb connect localhost
After a bit, I was able to connect and drive the device over adb:
$ ./adb devices
List of devices attached
localhost:5555 device
NOTE I'm not sure this is the whole story, as when testing this out for this answer, I deleted the dev-pc's adbkey and adbkey,pub and was still able to reconnect, so that seems a bit strange. It worked for me, but be aware, I'm not sure the mechanism.
In Android studio, Run menu > Run shows OFFLINE ... for the connected device.
Below is the procedure followed to solve it:
(Read the below note first) Delete the ~/.android/adbkey (or, rename to ~/.android/adbkey2, this is even better incase you want it back for some reason)
Note: I happened to do this step, but it didn't solve the problem, after doing all the below steps it worked, so unsure if this step is required.
Run locate platform-tools/adb
Note: use the path that comes from here in below commands
Kill adb server:
sudo ~/Android/Sdk/platform-tools/adb kill-server
You will get a Allow accept.. message popup on your device. Accept it. This is important, which solves the problem.
Start adb server:
sudo ~/Android/Sdk/platform-tools/adb start-server
In Android studio, do Run menu > Run again
It will show something like Samsung ... (your phone manufacture name).
Also installs the apk on device correctly this time without error.
Hope that helps.
Here is how I did it:
First you need to run the emulator on the host computer. I used Android Studio and I had to close it because I noticed that the adb process kept spawning.
Start port-forwarding using SSH in the development computer.
ssh -L 5554:localhost:5554 -L 5555:localhost:5555 user#emulator-host-ip
copy adbkey and adbkey.pub files found at: C:\Users\[your user]\.android from the host computer to the development computer. this step should get ride of the unauthorized problem
in the development computer kill the adb server and lookup connected devices:
$ ./adb kill-server
$ ./adb devices
List of devices attached
localhost:5555 device

ADB and cloned VBox emulators - not detected

I want to provide each user of my application a separate android emulator in the background. To achieve this, I clone the VMs in the following way:
vboxmanage clonevm <uuid> --snapshot <suuid> --name test_clone1 --register
vboxmanage clonevm <uuid> --snapshot <suuid> --name test_clone2 --register
vboxmanage startvm test_clone1
vboxmanage startvm test_clone2
Both VMs are created and started correctly. However, running ADB, the tools merely recognizes one of them:
adb devices
List of devices attached
emulator-5554 device
The original VM has 2 Network adapters, one host-only, the other one NAT with TCP port 5555 forwarded. Further, they have a different IP address after startup.
Can somebody help what I have to change in the settings/creation of the clones so that ADB recognizes all clones?
Thanks in advance
I did find a way
adb connect <clone1_ip>:<port>
adb connect <clone2_ip>:<port>
Now both are showing up when I issue adb devices.

Getting "error: closed" twice on "adb reverse"

I am trying to reverse-forward port through ADB, but it just returns cryptic error of error: closed. Normal forwarding works. Session snippet:
$ adb forward tcp:59778 tcp:59778
$ adb forward --list
015d2109ce0c1a0f tcp:59778 tcp:59778
$ adb forward --remove-all
$ adb forward --list
$ adb reverse --list
error: closed
error: closed
$ adb reverse tcp:59778 tcp:59778
error: closed
error: closed
I am connecting via USB to non-rooted Nexus 7 2012 Android 4.4.4 from Windows 7 Pro x64 on Boot Camp.
adb reverse was introduced in Android 5.0
Since adb reverse is not supported in Android versions lower than 5.0, you need to use an alternative method, for example connecting via Wi-Fi instead. If you are using React Native, Facebook has added official documentation to connect to the development server via Wi-Fi. Quoting the instructions for MacOS, but they also have them for Linux and Windows:
Method 2: Connect via Wi-Fi
You can also connect to the development server over Wi-Fi. You'll first need to install the app on your device using a USB cable, but once that has been done you can debug wirelessly by following these instructions. You'll need your development machine's current IP address before proceeding.
You can find the IP address in System Preferences → Network.
Make sure your laptop and your phone are on the same Wi-Fi network.
Open your React Native app on your device.
You'll see a red screen with an error. This is OK. The following steps will fix that.
Open the in-app Developer menu.
Go to Dev Settings → Debug server host for device.
Type in your machine's IP address and the port of the local dev server (e.g. 10.0.1.1:8081).
Go back to the Developer menu and select Reload JS.
Follow these steps carefully.
Note: All commands need to run inside a project only.
Run this command first:
npm react-native start
Open another window in the same project and run:
curl "http://localhost:8081/index.android.bundle?platform=android" -o "android/app/src/main/assets/index.android.bundle"
This will create index.android.bundle in the assets folder
Run:
npm react-native run-android
Now you can get apk in the build folder which will work fine.
adb reverse requires Android 5.0+. For devices previous to that, you'll need to use a workaround like so.
If you have busybox installed on your Android device (most Genymotion images do), you can emulate adb reverse using this incantation:
adb shell busybox nc -ll -p {guest port} -e busybox nc {host IP} {host port}
In this case, "guest" is the Android OS running in the emulator and "host" is the computer running the emulator.
cause of adb reverse isnt working on android prior 5 you could propably use adb forward with a service listening on android and tunneling other connections through this inbound connection. I am doing this mostly with ssh, but you would need an ssh server on android. you than can connect using ssh -R incommingreverseportonandroid:hostyouwanttoforwardto:portyouwanttoforwardto sshuseronandroid#localhost -p portyouhaveusedforadbforwaqrdtoaccessandroidssshserver
but i dont know how to enable an ssh server on android and maybe there is a better way cause ssh uses encryption which isnt needed over usb and using up cpu.
i am using this way with my server to share a service when i am forced behind a nat...
hope someone will find a way to bring this teoretical way into practical possibility
Just use 10.0.2.2 instead of localhost/127.0.0.1 for your hostname. It will directly try to connect to the port on the host machine (same affect as reverse).

adb forward not working

adb port forwarding is not working for me and your insight is appreciated.
The following command is what I am trying
./adb forward tcp:5985 tcp:5984"
I don't see any errors(in logcat) but it just fails silently. When I try the following command
curl localhost:5985 after that, I get "curl: (56) Recv failure: Connection reset by peer"
When I try curl localhost:5984, I do see a message as I have a process running on port 5984 (Couchbase server).
I don't think this is an issue with adb itself as all other adb commands are working. Amongst other things I have tried are
a) kill-server followed by start-server (with sudo mode as well)
b) Restarting my machine.
Needless to say, neither of these have worked. I am working on x64 Ubuntu 11.10.
Please note that I am working with the emulator and my emulator device is running.
I do see other messages in logcat just not this one.
Thanks
-Venu
Have you read this document from Google?
https://developers.google.com/chrome/mobile/docs/debugging
It explains that you have to first make sure you can see your device with
adb devices
Then in Chrome on your Android device, go to Open Settings > Advanced > Developer tools and check the Enable USB Web debugging option as shown here:
Then enter the follow command:
adb forward tcp:9222 localabstract:chrome_devtools_remote
And go to this URL in Chrome on your desktop:
localhost:9222
Does that work?
On the original question , the answer is to make sure your device emulator is running. On Ubuntu you can use: netstat -tan to see the TCP ports that your development machine is listening on. Usually the port is 5554. When the emulator is not started, there will not be a process listening on this port.
Well, I finally got there. I'm not sure which one of these finally fixed the issue (but most are helpful):
ensuring that /etc/udev/rules.d/##-android.rules was chmod a+rw so that we don't need to sudo adb and can edit it again
On Ubuntu 12.04 the ATTRS{idVendor} is the simple 4 hex code (some pages will encourage you to take the full lsusb ####:#### code
I now do not have the SYMLINK+="android_adb" entry in udev
adb devices still shows ???????????? instead of my device code (but works now)
adb shell actually returns a # prompt
adb usb breaks it (it was not returning with curl which I thought was an improvement on the error, but no - it breaks it worse)
There is a bug in adb forward, such that small, fast data connections are simply dropped:
emulator> nc -lk 9998
host> adb forward tcp:9900 tcp:9998
host> date | nc localhost 9900 # Does not arrive at the emulator
host> ( date ; sleep 0.1 ) | nc localhost 9900 # Does arrive at the emulator
That said, when I try the above with curl, that data gets through - presumably because curl holds the socket open in the same way that (date ; sleep 0.1) does.
This issue started happening for me when I updated Android SDK Platform Tools from version 29.0.2 to 29.0.3
I followed this How to downgrade my SDK version?
Basically, you need to downgrade Android SDK Platform Tools to version 29.0.2:
Find your Android SDK folder
Rename platform-tools to platform-tools-29-0-3 (incase something goes wrong)
Download Android SDK Platform Tools 29.0.2 for your machine e.g. http://dl-ssl.google.com/android/repository/tools_r29.0.2-windows.zip
Extract it into your Android/SDK folder
And you are done

What is the ADB?

I keep reading tutorials where I'm supposed to enter something into the ADB command line and that it's in my Android sdk/platform-tools. So I find it, click on it, and a black screen comes up for about 2 seconds and while it's up, it scrolls through a bunch of text. So how am I supposed to use this "adb"?
It is called the Android Debug Bridge, and the Android Developers Site documentation does a better job of explaining it than I can:
http://developer.android.com/guide/developing/tools/adb.html
If you are looking for the adb command line, navigate to <sdk>/platform-tools/ and run
adb.exe shell
from the command line.
Pretty sure that is well documented since day 1 on the Android Debug Bridge
Android Debug Bridge (adb) is a versatile command line tool that lets
you communicate with an emulator instance or connected Android-powered
device. It is a client-server program that includes three components:
A client, which runs on your development machine. You can invoke a
client from a shell by issuing an adb command. Other Android tools
such as the ADT plugin and DDMS also create adb clients. A server,
which runs as a background process on your development machine. The
server manages communication between the client and the adb daemon
running on an emulator or device. A daemon, which runs as a background
process on each emulator or device instance.
So plain old English, ADB can be found on %ANDROID_HOME%/platform-toos/, and it's this magical command line that allows you to comunicate with your mobile device, either a physical or a Virtual device (AVD), so whenever you deploy you are passing the application through the device thanks to the ADB on a specific client port on your computer to the daemon port on the device.
Interesting things you can do with it?
Logcat: ./adb logcat allows you to see the log trace of each proces.
Install: ./adb install allows you to install apk to the device.
Killing:./adb kill-sever
Starting:./adb stat-server
Enter SQLite3: adb -s your_device shell
Use the monkey: adb shell monkey -v -p your.app.package 500 to
generate random events
And a lot more! Read the documentation it's beatiful and self-explanatory.

Categories

Resources