retrofit onFailure() keeps triggering on connecting to localhost - java

I want to connect to my localhost server for testing my app. For this reason, I am using the retrofit library. This is my interface class, which defines the url to connect to:
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface PostInterface {
String JSONURL = "http://80.0.0.13/";
#FormUrlEncoded
#POST("login_screen/backend.php")
Call<String> getUserLogin(
#Field("input") String input,
#Field("username") String uname,
#Field("password") String password
);
}
I am calling this interface in my java code:
Call<String> call = null;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(PostInterface.JSONURL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
PostInterface api = retrofit.create(PostInterface.class);
call = api.getUserLogin("sign in", "abc", "abc#xyz");
if (call != null) {
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.body() != null) {
Log.d("success",response.body());
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), t.toString(), Snackbar.LENGTH_SHORT);
snackbar.show();
}
});
}
Strangely, the onFailure() method keeps triggering everytime with the following throwable:
javaSocketTimeoutException: Failed to connect to /80.0.0.13 (port 80)....
But when I try the url in my android browser or pc browser, it works fine.
Things I have checked:
The project is stored inside C:\xampp\htdocs, having the exact same hierarchy as in my live server location.
Both Apache and SQL ports are open in my xampp control panel.
My localhost port number is default 80
When I run the app in my emulator using this ip http://10.0.2.2:80/, then it works fine
Why is the app failing to connect to my local server?
EDIT: I can access my site from my phone browser using my pc ip address, but when I want to access it from the app, then the onFailure() triggers

After much struggling, I finally found the solution from a post in github:
Turn on USB Tethering & USB Debugging Mode in your mobile.
Connect your mobile to your laptop/desktop through USB.
Now just change the ip address (run "ipconfig" in cmd)

This is because localhost is not a valid URL for android.
The localhost is a loopback address, which means that the network request will be handled by current device by some application (PHP server).
So, when you enter localhost on your machine (PC/laptop), it will check for server application listening at specified port (in your case 80) and will forward that request to the server application. In your case it is XAMPP which is listening at port 80.
But, when you goto an Android application, there is no server application running on android device or emulator since they are different device. Hence you get 404 error for localhost on Android.
To fix this, simply get the IP address of your PC (using ipconfig command) and use that instead of localhost.
E.g.: In cas the IP address is 192.168.0.129, then your URL would be http://192.168.0.129:80/

Related

Sending a command to android things from an android device

I am recently working on a project that requires sending a command from my android mobile app to the android things on my raspberry pi 3. How can I achieve this through a WiFi connection?
I only need to send a String to the device.
If one of your devices isn't connected to internet, you could :
Option 1 :
use Google Nearby Connections API , the API choose the best way to communicate (eg: Bluetooth, Wifi...).
See https://github.com/googlesamples/android-nearby/tree/master/connections
Option 2 :
Use Socket to communicate but your devices need to be on the same network. If they aren't connected to the same network, you can connect them using WIFI P2P.
Using Android Things, you can use the Nearby Messages API, which gives you the ability to communicate to and transfer messages between two Android devices within their apps. Here's a code snippet:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mMessageListener = new MessageListener() {
#Override
public void onFound(Message message) {
Log.d(TAG, "Found message: " + new String(message.getContent()));
}
#Override
public void onLost(Message message) {
Log.d(TAG, "Lost sight of message: " + new String(message.getContent()));
}
}
mMessage = new Message("Hello World".getBytes());
}
#Override
public void onStart() {
super.onStart();
...
Nearby.getMessagesClient(this).publish(mMessage);
Nearby.getMessagesClient(this).subscribe(mMessageListener);
}
#Override
public void onStop() {
Nearby.getMessagesClient(this).unpublish(mMessage);
Nearby.getMessagesClient(this).unsubscribe(mMessageListener);
...
super.onStop();
}
If you use system like Raspbian you can transform your Raspberry into a server.Then, You will have different ways to send your command:
Option 1: Set up an Http server on your raspberry (PHP, NodeJS, JEE, ...) and send command via HTTP Request.
Option 2: Set up a Socket Server on your raspberry (Socket.io, raw socket, ...) and send command via socket client
Option 3 Set up MQTT Server on your raspberry and send command via MQTT client (this last option is the way to go when talking about Internet of Things). Note that the program which receive command should implement MQTT Client as MQTT is based on pub/sub pattern.
You can use nanoHttpd on Android things and other library such as retrofit or volley on the Android device.
Check out this example for controlling a car via an Http API: https://github.com/plattysoft/IotCar

Issue with connecting Android phone to mac computer on the same wifi network

I'm running a server on my macbook at port 5000. I have an Android application on my phone (on the same wifi network as my laptop) that needs to talk to the server on my laptop.
On my laptop, when I type the following into my web browser I get the proper test page I created:
http://localhost:5000/test
Now, to get my computer's IP on my current wifi network I used the IP shown in the Network Preferences (on my computer it is 192.168.1.128). I also used the ifconfig command to verify this is the correct IP address.
Now, when I visit the following on my computer, I get a generic "Cannot load this web page" error.
http://192.168.1.128:5000/test
When I make a request to that address in my Android application (again, the phone is on the same wifi network), I get:
failed to connect to /192.168.1.128 (port 5000) after 2500ms: isConnected failed: ECONNREFUSED (Connection refused)
Which is weird, as my server is still running - I run that localhost url from above to verify this.
If it makes any difference, I'm using the StringRequest from com.mcxiaoke.volley:library:1.0.+ and am only expecting "Hello, world" back. I don't at any step in the process deal with JSON, encoding or decoding, but it's just text so it should come through and print out on my Android phone.
If it matters, here's the Android code:
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://192.168.1.128:5000/test";
System.out.println("Requesting...");
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// TODO
System.out.println("++++++++++" + "onResponse()");
System.out.println("++++++++++" + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO
System.out.println("++++++++++" + "onError: " + error.getMessage());
}
});
queue.add(stringRequest);

Trying to access localhost from a Java restAdapter on Android

I'm making an android application wich uses a web service. To access to it, we use a restAdapter. This is the code:
private String URL_PLACE = "http://myaddresstomywebservice";
public RouteCLlegar(Context ctx) {
restAdapter = new RestAdapter.Builder()
.setEndpoint(URL_PLACE)
.build();
cLlegar = restAdapter.create(CLlegar.class);
}
When we access the web service hosted on the web, it works, but when we use localhost, it doesn't.
private String URL_PLACE = "http://localhost:53285";
public RouteCLlegar(Context ctx) {
restAdapter = new RestAdapter.Builder()
.setEndpoint(URL_PLACE)
.build();
cLlegar = restAdapter.create(CLlegar.class);
}
It gives this error:
24963-25327/ni.femer.busesmg.app I/ERRORīš• el error java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 53285) after 15000ms: isConnected failed: ECONNREFUSED (Connection refused
How can i access localhost from my rest adapter?
You can run your application on an Android emulator and use 10.0.2.2 instead of localhost.
You can use a local IP address of your PC (check it with ipconfig, should be something like 192.168.1.x), if it's on the same wireless network with your Android device.
Don't forget to specify also a port number.
I would suspect, localhost is your Android device. If you realy want to access something on localhost, you would have to deploy a http Server in your Android device.

Android connection to localhost

I'm trying to connect my android application to a local host url thanks to wamp server but it doesn't work. My goal here, is to fetch json data and parse these data. For my test, i'm using a device not the emulator and i use permission in AndroidManifest.xml :
<uses-permission android:name="android.permission.INTERNET" />
My url looks like this :
String url = "http://10.0.2.2:8080/tests/PhpProject1/connectionBDD.php";
i tried :
http://localhost/
http://10.0.2.2:8080/
http://10.0.2.2/
But it never worked so far :
java.net.ConnectException: failed to connect to localhost/127.0.0.1 (port 80): connect failed: ECONNREFUSED (Connection refused)
failed to connect to /10.0.2.2 (port 8080): connect failed: ETIMEDOUT (Connection timed out)
java.net.ConnectException: failed to connect to /10.0.2.2 (port 80): connect failed: ETIMEDOUT (Connection timed out)
Then i tried with a json url test found on the internet : http://headers.jsontest.com/
It worked really good and i got json data at this address. So i guess my code is good and the issue here is my localhost url, i don't know what should be its exact form..
I read many threads about it but i didn't find a solution.
Here my code :
Main activity :
public class MainActivity extends Activity {
private String url = "http://10.0.2.2:8080/tests/PhpProject1/connectionBDD.php";
private ListView lv = null;
private Button bGetData;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final JsonDownloaderTask task = new JsonDownloaderTask(this);
lv = (ListView) findViewById(R.id.list);
bGetData = (Button)findViewById(R.id.getdata);
bGetData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
task.execute(url);
}
});
}
public void jsonTaskComplete(JSONArray data){
//todo
}
}
AsyncTask :
public class JsonDownloaderTask extends AsyncTask<String, String, JSONArray> {
MainActivity ma;
public JsonDownloaderTask(MainActivity main){
ma = main;
}
#Override
protected JSONArray doInBackground(String... url) {
JSONParser jParser = new JSONParser();
// Getting JSON from URL
JSONArray jsonArray = null;
try {
jsonArray = jParser.getJSONFromUrl(url[0]);
} catch (IOException e) {
e.printStackTrace();
}
return jsonArray;
}
protected void onPostExecute(JSONArray data){
ma.jsonTaskComplete(data);
}
}
JSONParser :
public class JSONParser {
String data = "";
JSONArray jsonArray = null;
InputStream is = null;
public JSONParser(){}
// Method to download json data from url
public JSONArray getJSONFromUrl(String strUrl) throws IOException{
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
is = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
is.close();
data = sb.toString();
//br.close();
jsonArray = new JSONArray(data);
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
is.close();
}
return jsonArray;
}
}
IP-address 10.0.2.2 is used to fetch data from the emulator.
Localhost will always point to the emulator/android device running the application.
To let your device fetch data from your pc, it should be in the same network (connected by WiFi to your router) and you should use the local IP-address of your pc (normally a 192.168.1.x-number).
If you try to connect to "localhost", it will resolve to the Android device, not to your own localhost (unless you are running within the emulator). What I recommend for development is to add an overflow menu in the action bar that has an entry named "Settings" that provides a Settings activity for specifying application settings, and to have a "Developer options" entry in "Settings" that lets you specify a custom server address to use. During development, you can use this option to enter a custom server address for your app. (You will need a real server address that is actually reachable over the Internet rather than using localhost for this).
First you have to bind the IP address of the machine where your server is running in the eclipse settings.
You can do this like this.
Right click on the PHP project in the eclipse then Run Configuration then In the Web Application where you will find the Argument tab. Now here give the port and LAN IP address of your machine on which your server is running.
Something like this --port=8888 --address=192.168.1.6 then update the URL to http://192.168.1.6:8080/tests/PhpProject1/connectionBDD.php
Here in my case this is my LAN IP address 192.168.1.6, there you will have to find it using the network command like ipconfig , ifconfig and use that IP address.
if you are using your phone instead of emulator and running services on localhost then in url instead of '10.0.2.2' use IP address of your PC.
I solved it by:
1. Adding another android permission in the manifest: "android.permission.ACCESS_NETWORK_STATE"
2. As I'm using xampp, I've shared the xampp folder of the desktop in the network.
3. The xampp is running in a desktop whose ip is 192.168.x.x so the webservice's url instead of beign "http://localhost/myapi..." is "http://192.168.x.x/myapi..."
I tested the app using the emulator and also in a device. Both cases works out.
One simple way i know is keep mobile data on and share wifi . Connect your laptop or computer to this wifi . Now see ip of ur laptop or desktop. Call service from ur phone . Since your phone and your computer are in same network now.
I assume you are trying to access web service available on your PC from either an android simulator or a real device.
For an android emulator, you must NOT just use "localhost", because "localhost" means android emulator itself, NOT the host PC.
you need modify the /etc/hosts file or the simulator or real device. add a line like "192.168.0.100 service.local".
I tried "10.0.2.2:80/mysitename/page.php"
Miracle happened, it's working now.
I am on Mac and using XAMPP for server.
You can change port no. to 80 and try.
port 8080 was not working for me!
Cheers.
Just Install the "conveyor by Keyoti" the extension in Visual studio and it will generate a url according to your ip address automatically. here's the link:
conveyor
so far so good....!

How to discover the IP address of a Tomcat server on a network?

I have a Android application which consumes a webservice on a local network. There's a config screen where the user inform the server IP address, which is running Apache Tomcat.
I'm looking for a way to auto-detect the server based on the current connected wi-fi network.
i.e: The smartphone's IP is 10.1.1.90 and the server IP is 10.1.1.254.
Is there a way to achieve this? I'm thinking on using ping, but I don't know if is a good ideia.
The way I understand it, you need to discover IP of your tomcat server and connect it using your client.
I am assuming , both the server and client is in your control.
One simple way can be to use jGroups Cluster.
You can make your tomcat discoverable
Client can discover it using the name of the cluster you have provided .Refer the JChannel API that Jgroups uses
I simulated it making following server class
public class TomcatServer {
JChannel channel;
private void start() throws Exception {
channel = new JChannel(); // use the default config, udp.xml
channel.connect("TomcatCluster");
}
public static void main(String[] args) throws Exception {
new TomcatServer().start();
}
}
The simulated client class
public class MobileApp extends ReceiverAdapter {
JChannel channel;
private void start() throws Exception {
channel = new JChannel(); // use the default config, udp.xml
channel.setReceiver(this);
channel.connect("TomcatCluster");
channel.close();
}
public static void main(String args[]) throws Exception {
new MobileApp().start();
}
The client will provide you following information
GMS: address=MACHINENAME-47879, cluster=TomcatCluster, physical address=xxxxx:0:xxx:xxxx:xxxx:xxxx:xxx:xxxx:xxxx
** view: [MACHINENAME-31239|1] [MACHINENAME-31239, MACHINENAME-47879]
Where MACHINENAME-47879 is the client machine and port & MACHINENAME-31239 is the tomcat server name and port
Do you want to detect "a tomcat server" or "your tomcat server" ?
I mean, do you have any way to custom your server ? If it's the case, then you could create a very simple test page on your server (say a "Hello" JSP page), which your Android application could look for.
If your Android gets a "Hello" result with a GET request on http://<tomcat_ip>/hello.jsp, then you may assume that the tomcat is online.
If you can't add this test page, then you can test any page which the server is supposed to serve. (even a 404 page which sometimes is not configured well, and shows the tomcat version...)
Tomcat response headers can contain the xpoweredBy field that would advertise Tomcat if enabled. However it is most often disabled due security considerations, and even disabled by default. You however could re-enable it if you need to auto-detect exactly your Tomcat servers. From the other side, indeed, if you can place a web page on your server, you can simply place a marking page with the agreed signature.
If the server IP is unknown, I would propose the following ways to detect the server on the network:
The most straightforward way is to do the breadcast ping (ping -b broadcast_address where breadcast address can be computed here, for instance). All network devices that are configured so would reply, then verify as explained above which one is the server. However pinging broadcast address requires a rooted phone. Also the router may not support.
Your DHCP service (most likely your router) can often be configured to issue always the same IP address for the same MAC address of your server network card.
If the server is a desktop computer or laptop, it could show its address as QR code on display. It is possible for a smartphone to scan the code from the screen, and this is way easier than to enter IP address through the touchscreen. QR code can also include auto-generated password for extra security.
If there is wireless router with the possible login where both server and client are connected, the internal pages of that router often contain the relevant IP addresses. You would need to implement logging into the router and doing some screen scrapping.
I made an Android app which used a local server in the WLAN. I made the terminal (the phone) broadcast it's own IP address, which the server then picked up.
I used MultiCast class on the phone, which added the ip-address of itself to the payload. The server always has a thread in multicast read class that obains the payload of the packet (which is the terminals ip-address). Set the terminal in datagram read state and send the servers ip-address to terminal.
Maybe are better ways, but a great way to get the ip-addresses of unknown terminals in the network.
The way i had resolved this problem is with the use of enumerations.
public String getLocalIpAddress()
{
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (Exception ex) {
}
return null;
}
}

Categories

Resources