I'm porting an Linux C++ application to Android NDK and my app invokes ping to the shell to see the status of another machine for logging purposes. On my android port this fails for localhost:
# ping -c 10 localhost
ping: unknown host localhost
If I give another web address that appears to send, but no response is seen:
# ping -c 1 google.com
PING google.com (74.125.239.136) 56(84) bytes of data.
--- google.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Is localhost expected to work on Android to refer back to the android itself (not the host machine running the emulator as discussed here)? If not, is there some other way that will work?
Is ping expected to work on the Android emulator for Mac OSX or must I do something to allow the emulator to see the network fully?
Related
I did a question since I'm testing my react-native/express app by using usb debug on android and I'm still getting a network request failure:
How to connect to the express development server using adb reverse?
Since I couldn't find a solution I tried to read the docs and figure out how it's the communication among different parts.
Cases
Commands used are those described in React-Native docs but it could differs. Although I guess there are not too many options:
https://reactnative.dev/docs/running-on-device
https://reactnative.dev/docs/signed-apk-android#testing-the-release-build-of-your-app
Case 1: running only using the dev machine and emulator
Case 2: running using the usb debug
Case 3: wifi (I didn't try yet)
Case 4: uploading to play store by bundleRelease
Elements:
Dev machine:
Local host: 127.0.0.1
Local IP (from windows 10: settings, network & internet, wi-fi; eg 192.168.1.1)
Server
Device
Emulator
ADB
Daemon
Ports usage:
From my dev machine:
Server (eg 5000)
React-native: 8081 (default)
Daemon: 5037
From device: I guess is used only the 8081 port.
Emulator:
10.0.2.2 Special alias to your host loopback interface (i.e., 127.0.0.1 on your development machine)
10.0.2.15 The emulated device network/ethernet interface
127.0.0.1 The emulated device loopback interface
Connections
React-native emulator mounts over the 8081 port of the dev machine local host. Since it "replaces" the local host adress if you wanna access to another port you have to use the alias 10.0.2.2 (eg server running at 5000 will be: 10.0.2.2:5000).
Till then my app works well setting the communication following the instructions above mentioned. But when I try to use the USB debug I can't connect to the server and I'm getting puzzled about what's going on behind the scene.
I wrasp the idea of the emulator running as an isolated router to which is connected the tested device. I guess Daemon runs as a background process reloading every time that the server file is edited. But I can understand why I can't connect to the server.
Resources
Android
https://developer.android.com/studio/run/emulator-networking.html
Note that the same address assignments are used by all running emulator instances. That means that if you have two instances > running concurrently on your machine, each will have its own router and, behind that, each will have an IP address of 10.0.2.> 15. The instances are isolated by a router and can not see each other on the same network. For information about how to let > emulator instances communicate over TCP/UDP, see Interconnecting Emulator Instances.
Also note that the address 127.0.0.1 on your development machine corresponds to the emulator's own loopback interface. If you > want to access services running on your development machine loopback interface (a.k.a. 127.0.0.1 on your machine), you should > use the special address 10.0.2.2 instead.
Finally, note that the pre-allocated addresses of an emulated device are specific to the Android Emulator and will probably be > very different on real devices (which are also very likely to be NAT-ed, specifically, behind a router/firewall).
http://adbcommand.com/adbshell
https://developer.android.com/studio/command-line/adb
Locates emulator for each connection by a using a pair of ports (console/adb) in the range of 5555 to 5585
When the server starts, it binds to local TCP port 5037 and listens for commands sent from adb clients—all adb clients use > port 5037 to communicate with the adb server.
Adb graph connection of my own (this is in case of several devices connected but if I'm not wrong it'll work similarly to one device connected):
devMachine: client -- server
-- daemon -- || -- daemon -- : running device 1
-- daemon -- || -- daemon -- : running device 2
-- daemon -- || -- daemon -- : running device 3
https://developer.android.com/training/articles/security-config
On my Android emulator device I have deployed HTTP server on port 8080
> adb -s 127.0.0.1 shell
generic_x86:/ $ netstat -atn
Active Internet connections (established and servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 0 0 :::8080 :::* LISTEN
tcp6 0 0 ::ffff:10.0.2.16:47344 ::ffff:66.102.1.18:5228 ESTABLISHED
However, when I try to access it from the host the port seems to closed:
curl http://127.0.0.1:8080
curl : Unable to connect to the remote server
In my host Resource Manager I am not seeing any process listening on that port
Why is the port not visible on host?
The official documentation says that (thanks to #Selvin):
Each instance of the emulator runs behind a virtual router/firewall service that isolates it from your development machine network interfaces .
and then explain how to open specific ports by
Using network redirection
In my case implementation the steps helped
telnet localhost 5554
auth ... # with token
redit add tcp:8080:8080
quit
And voila, HTTP server has become available on my host machine.
Now,
I've trawled through many of the answers here regarding socket access via native code on Android, and others regarding socket access for "androidTest" instrumented tests, but none are able to fully explain some odd behaviour I'm seeing.
Android Studio 2.3.3 on Windows 10, NDK 15.1.x, build tools 25.0.3. Building with Cmake. I am porting some native code over to Android intended to be distributed as a library that is wrapped in a Java JNI-based API. This part seems to be working fine; at least I can debug and log into the native code and see where things go wrong.
I've created a few instrumented tests to exercise the JNI, but it looks like the native side does not have access to sockets, even if the test app that Android Studio wraps up for your intrumented tests does (i.e., it has the INTERNET permission applied, and I can see that it is part of the pushed manifest of the test app. I also applied the ACCESS_NETWORK_STATE perm in a fit of pique.)
That is, parts of the library know how to set up and use TCP sockets (datagram and stream; in this case stream) and resolve DNS, which fails (This might be a bug in my port, since the device itself still seems to resolve DNS based on the adb shell output below). If I test with an IP address it retries until it fails. Each call to socket() returns an ERRNO of 11 EAGAIN ("Try again").
If I use the adb shell to login to the device under test over USB, I can ping and use curl, etc. But, as soon as I run-as as the test app I am no longer allowed to use any network device.
shell#venice:/data/data/org.clvrmnky.library.test $ ping www.example.com
PING www.example.com (93.184.216.34) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
^C
--- www.example.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2004ms
1|shell#venice:/data/data/org.clvrmnky.library.test $ ping -I wlan0 www.example.com
ping: SO_BINDTODEVICE: Operation not permitted
2|shell#venice:/data/data/org.clvrmnky.library.test $ curl -4 --verbose www.example.com/
* Trying 93.184.216.34...
* connect to 93.184.216.34 port 80 failed: Connection timed out
* Failed to connect to www.example.com port 80: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to www.example.com port 80: Connection timed out
7|shell#venice:/data/data/org.clvrmnky.library.test $
I won't paste it here, but wlan0 (and others) exists and is UP with a valid, reachable IP address. It is "Link encap:UNSPEC" which I admit I don't fully grok.
I'm making an assumption that the app failing on the successive socket calls and the inability to bind to a network device in and use it in an adb shell are related in some manner, but if someone has a reason why this may not be so, please let me know.
I've tried:
Invoking the test methods in a background thread, just in case the instrumented tests were running in the test app main thread.
Setting the StrictMode thread policy to permitAll() in the #Before clause of the test class.
Running with and without the INTERNET permission set in the test manifest. Without this permission it reaches the native code, but fails much earlier in the initialization. I'd have to dig into my notes to fetch more details about that. I assume that I need this permission. (Side note: if I enable INTERNET then the remote debugger can no longer attach to the device, so I can debug via logs only.)
It looks like instrumented tests, at least as of this writing, do not support access to raw sockets through the NDK. The .test app that is auto-created seemed to have everything it needed in the manifest (I checked base.apk right from the device).
Once a DemoApp was created with identical manifest settings I was able to open sockets, connect to them, do name lookups, etc. Furthermore, I was able to access the network via adb shell when running as ("run-as") the DemoApp.
There is still something strange going on, as I created a separate JNI app that opens sockets, and hacked an instrumented test against that. At least briefly adb shell running as ext.other.app.test did have internet access.
I have a native C++ app which is supposed to run on an Android device. The application crashes at the startup, most likely when calling a function from a linked library. I am trying to debug it with gdb, but I can't succeed.
I am starting gdbserver on the Android device on some arbitrarily picked port (2000):
shell#msm8996: gdbserver :2000 my_app
Process my_app created; pid = 3420
Listening on port 2000
Now I am trying to attach to this process on my Host system (Windows 7) with gdb that was provided in Android-NDK.
C:\> gdb
(gdb) attach 3420
Can't attach to process.
(gdb) target remote :2000
:2000: The system tried to join a drive to a directory on a joined drive.
What is the problem?
EDIT:
Prior to running gdb I forwarded the port 2000 using adb:
adb forward tcp:2000 tcp:2000
This at least helped me to establish some communication, but:
(gdb) target remote :2000
Remote debugging using :2000
warning: Architecture rejected target-supplied description
Remote 'g' packet reply is too long: 00000000000000000000000000000...
On the device side:
Listening on port 2000
Remote debugging from host 127.0.0.1
readchar: Got EOF
Remote side has terminated connection. GDBserver will reopen the connection.
Listening on port 2000
You are most probably using different architecture / version of gdb. When you start the gdb, it displays a line like (I am showing what my GDB shows):
This GDB was configured as "--host=x86_64-linux-gnu
--target=arm-Linux-android"
Check if this matches with your phone's architecture.
Downloading the correct GDB version may solve your problem.
Background Info
I got a Samsung GT-S5830, running Android 2.3.4. The device has been successfully rooted.
I edited the WIFI settings to connect to my home network, so now I can surf the Internet event though there is no simm card. The network configuration is static, as follows:
IP : 192.168.0.7
Mask : 255.255.255.0
Gateway : 192.168.0.1
DNS1 : 192.168.0.1
In my local machine, I've installed the Android SDK tools (ADB).
From that console, I issue the following commands:
1) C:\> adb shell
2) $ su
3) # (now successfully logged as root)
Once I am logged in as root (the symbol # is showing), I can successfully ping the following addresses:
192.168.0.7 (the handheld address)
192.168.0.1 (the gateway)
127.0.0.1 (loopback)
I also can ping intranet sites such as Google or FB
The problem
However, I can't ping any other machine in the intranet, eg 192.168.0.4, which is one of my local servers.
The command netcfg shows the following information:
Did anyone had to face the same problem?
Many thanks for your help.
Well, I couldn't work out what's causing the problem, but I've found a workaround.
Although the device is connected to the intranet, it make the requests from the 'outside'. As you can see in the screenshot above, the network adaptor isn't anything like 'eth0' but 'wlan0'. In other words, it's searching for the public IP of the web server
What I did is to configure the firewall to accept inbound traffic on the port 80 (web). Doing this way, I was able to render my webpages on the device.