so I have created two separate apps, one acts as a client & the other acts as a server. Both devices are connected using hotspot:
Connection between the devices is successful. For transferring data from the server to the client, I am using the below code:
public static String downloadDataFromSender(String apiUrl) throws IOException {
InputStream is = null;
try {
URL url = new URL(apiUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
/* Starts the query */
conn.connect();
conn.getResponseCode();
is = conn.getInputStream();
/* Convert the InputStream into a string */
return readIt(is);
} finally {
if (is != null) {
is.close();
}
}
}
But I keep getting the following error:
java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:343)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:205)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:187)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356)
at java.net.Socket.connect(Socket.java:586)
at com.android.okhttp.internal.Platform.connectSocket(Platform.java:113)
at com.android.okhttp.Connection.connectSocket(Connection.java:196)
at com.android.okhttp.Connection.connect(Connection.java:172)
at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367)
at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:130)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126)
at com.wifiscanner.utils.DownloadUtils.downloadDataFromSender(DownloadUtils.java:27)
at com.wifiscanner.tasks.SenderAPITask.doInBackground(SenderAPITask.java:29)
at com.wifiscanner.tasks.SenderAPITask.doInBackground(SenderAPITask.java:14)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
The url I am using in the download is this:http://192.168.43.1:52287/files
The connection is successful as I said. So not sure why I am getting network is unreachable. This happens intermittently and not always.
Could someone provide some detail on why this is happening?
Related
I have implemented HttpUrlConnection to send a request to a local http server (common LAN,Wifi,WifiAP). The code works perfectly fine for normal web servers (www.xyz.com), but fails to do so for local servers (192.168.x.y:z).
The code:
1) The function which makes the request
public static String getDef(String urlInput) {
URL url = null;
try {
url = new URL("http://" + urlInput);
Log.d("http", "calling " + url.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Connection", "close");
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.connect();
InputStream in = null;
in = (conn.getInputStream());
String response =readIt(in,5) ;
//response = org.apache.commons.io.IOUtils.toString(in, "UTF-8");
return response;
} catch (IOException e) {
Log.e("http","Error");
e.printStackTrace();
}
return "LocalClient didnt work";
}
2) The function which calls the above function.
new AsyncTask<String, Void, String>(){
#Override
protected String doInBackground(String... params){
try {
return LocalClient.getDef(URL);
} catch (Exception e){
e.printStackTrace();
}
return "Didnt work";
}
#Override
protected void onPostExecute(String string) {
message.append(string);
}
}.execute();
3)The request is received at the server with the following headers.
GET / HTTP/1.1
Connection: close
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; Nexus 5 Build/LYZ28E)
Host: 192.168.0.101
Accept-Encoding: gzip
It would be wonderful if someone could point me in the right direction.
I have also tried OkHttp,
public static String get(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
try {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
resp= response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return resp;
}
On using a normal webserver the response is properly returned (source) but while using a local server I get the following error
java.io.EOFException
W/System.err﹕ at com.android.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:95)
W/System.err﹕ at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:179)
W/System.err﹕ at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101)
W/System.err﹕ at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:628)
W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:388)
W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
W/System.err﹕ at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
W/System.err﹕ at com.demo.demo.http.LocalClient.getDef(LocalClient.java:56)
W/System.err﹕ at com.demo.demo.wifi.connector$2$2.doInBackground(connector.java:109)
W/System.err﹕ at com.demo.demo.wifi.connector$2$2.doInBackground(connector.java:105)
W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:292)
W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err﹕ at java.lang.Thread.run(Thread.java:818)
The problem was server-side and was resolved by using appropriate headers.
OkHttp still doesn't seem to work and the function "public static String getDef(String urlInput)" mentioned above works flawlessly.
It seems there's an open bug about this issue:
https://github.com/square/okhttp/issues/1518
They suggest adding android:vmSafeMode="true" to the manifest file.
I wrote an API in laravel, to accept POST request to receive parameters and save it in DB.
On success it responds back with a json returning the Order ID (Http response code 200)
{
"data": {
"order_id": 21
}
}
before it saves data in DB I validate the data and if there is a error it returns error message json (Http response code 400)
{
"error": {
"code": "GEN-WRONG-ARGS",
"http_code": 400,
"message": {
"cust_id": [
"The cust id may not be greater than 9999999999."
]
}
}
}
It works perfectly fine in browser
In Android call, when it is all ok e.g. http response code 200 I get the json.
But when error json is returned I never receive the error json, getInputStream() returns null.
private InputStream downloadUrl(String urlString) throws IOException {
// BEGIN_INCLUDE(get_inputstream)
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Start the query
conn.connect();
InputStream stream = conn.getInputStream();
return stream;
// END_INCLUDE(get_inputstream)
}
If there is error how can I change response code to 200 and send it in Laravel and then get the error json.
or in Android wow can I receive http body even if there is a response code like 400 or 404, like browsers get
1 is a workaround and 2 is the right way to do it.
Thanks,
K
After hours of struggle, I figured out the solution. getErrorStream() is the solution to this. I changed the code as following to get the error response if response code>=400.
private InputStream downloadUrl(String urlString) throws IOException {
// BEGIN_INCLUDE(get_inputstream)
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Start the query
conn.connect();
InputStream stream = null;
try {
//Get Response
stream = conn.getInputStream();
} catch (Exception e) {
try {
int responseCode = conn.getResponseCode();
if (responseCode >= 400 && responseCode < 500)
stream = conn.getErrorStream();
else throw e;
} catch (Exception es) {
throw es;
}
}
return stream;
// END_INCLUDE(get_inputstream)
}
Hope this will save someone tons of time
Thanks,
K
I'm using the following code for post requests
public String executeHttpPost(String uri, String data) {
HttpURLConnection conn = null;
URL url = null;
String s = null;
try {
url = new URL(uri);
conn = (HttpURLConnection) url.openConnection();
if (conn instanceof HttpsURLConnection) {
Log.d("HTTPS", "HttpsUrl");
}
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
DisplayResponseHeaders(conn);
s = readStream(conn.getInputStream());
Log.d("body", s);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
s = null;
e.printStackTrace();
} finally {
conn.disconnect();
}
return s;
}
When I use it over http, all works good , but over https I get
java.io.EOFException
at libcore.io.Streams.readAsciiLine(Streams.java:203)
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:573)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:821)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:283)
libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
ru.fors.remsmed.fragment.NetHelper.executeHttpPost(NetHelper.java:234)
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:424)
ru.fors.remsmed.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:287)
java.util.concurrent.FutureTask.run(FutureTask.java:234)
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
java.lang.Thread.run(Thread.java:856)
threadid=14: thread exiting with uncaught exception (group=0x40a71930)
I found the issue about recycling connections bug in httpsurlconnection and possible solution :
if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
conn.setRequestProperty("Connection", "close");
}
But it isn't work for me.
Try to change your code like this:
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded; charset: UTF-8");
byte[] output = data.getBytes("UTF-8");
conn.setFixedLengthStreamingMode(output.length);
os = conn.getOutputStream();
os.write(output);
os.flush();
os.close();
DisplayResponseHeaders(conn);
if (conn.getResponseCode() == 200) { // or other 2xx code like 204
s = readStream(conn.getInputStream());
Log.d("body", s);
}
else {
// handle error conditions like 404, 400, 500, ...
// now it may be necessary to read the error stream
InputStream errorStream = conn.getErrorStream();
// ...
}
AFAIK you should always close all streams you opened. I'm not sure whether conn.disconnect() is doing that for you.
If you want to code your HTTP(S) requests more conveniently, you can have a look at DavidWebb where you have a list of libraries helping you to avoid using cumbersome HttpURLConnection.
That EOFException suggests the response is malformed - perhaps lacking a blank line after the headers. Some HTTP client code is more forgiving in that case, for me iOS could handle my server responses fine but I was getting EOFException on Android using HttpURLConnection.
My server was using python SimpleHTTPServer and I was wrongly assuming all I needed to do to indicate success was the following:
self.send_response(200)
That sends the initial response header line, a server and a date header, but leaves the stream in the state where you are able to send additional headers too. HTTP requires an additional new line after headers to indicate they are finished. It appears if this new line isn't present when you attempt to get the result body InputStream or response code etc with HttpURLConnection then it throws the EOFException (which is actually reasonable, thinking about it). Some HTTP clients did accept the short response and reported the success result code which lead to me perhaps unfairly pointing the finger at HttpURLConnection.
I changed my server to do this instead:
self.send_response(200)
self.send_header("Content-Length", "0")
self.end_headers()
No more EOFException with that code. It's possible the "Connection: close" solutions trigger some behaviour on certain servers that might work around this (eg ensuring the response is valid before closing) but that wasn't the case with the python SimpleHTTPServer, and the root cause turned out to be my fault.
NB: There are some bugs on Android pre-Froyo (2.2) relating to keep-alive connections - see the blog post here: http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html. I'm yet to see convincing evidence of bugs with newer versions of Android.
private String urlPost = "http://192.168.1.66:8080/DataCollectionServlet/";
#Override
protected void doWakefulWork(Intent intent) {
// https://stackoverflow.com/q/14630255/281545
HttpURLConnection connection = null;
try {
connection = connection();
w("connection"); // allrigt
final OutputStream connOutStream = connection.getOutputStream();
w("GEToUTPUTsTREAM"); // I never see this
} catch (IOException e) {
e.printStackTrace(); // No route to host
} finally {
if (connection != null) connection.disconnect();
}
}
private HttpURLConnection connection() throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(urlPost)
.openConnection();
// connection.setDoInput(true);
connection.setDoOutput(true); // triggers POST
// connection.setUseCaches(false); // needed ?
// TODO : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
// connection.setRequestProperty("Connection", "Keep-Alive");
// connection.setRequestProperty("User-Agent",
// "Android Multipart HTTP Client 1.1"); // needed ?
return connection;
}
The server in 192.168.1.66:8080/DataCollectionServlet/ is up and running. My device IP is 192.168.1.65. I disabled both window's and the router's firewall to no avail.
EDIT - stack trace :
java.net.SocketException: No route to host
at org.apache.harmony.luni.platform.OSNetworkSystem.connect(Native Method)
at dalvik.system.BlockGuard$WrappedNetworkSystem.connect(BlockGuard.java:357)
at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:204)
at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437)
at java.net.Socket.connect(Socket.java:983)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:75)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:205)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:614)
at gr.uoa.di.monitoring.android.services.NetworkService.doWakefulWork(NetworkService.java:51)
at com.commonsware.cwac.wakeful.WakefulIntentService.onHandleIntent(WakefulIntentService.java:94)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.os.HandlerThread.run(HandlerThread.java:60)
Comments : Again, the phone and PC are both connected to the same router wirelessly (same SSID)
Android 2.3.7 Eclair, HTC Nexus 1 - could it be a bug ?
EDIT 2013.11.13 : still interested in ana explanation of my answer
Well well - disabling the (WPA-PSK) Encryption on the router I connect alright. I would accept as an answer a (programmatic) work around
EDIT : entering the URL into the android device's browser I do see the doGet() page. I reenabled all firewalls - the only thing that makes a difference is toggling encryption on and off
ich have written an app for android which has to download data from a website. All in all it works pretty well but i heard from some users that they the internet connection doesn't work when they use internet access via mobile internet. With the WLAN there are no problems and on my mobile phone it even works with mobile internet. I already ensured myself that the users who has got these problems do have internet access on other apps with their mobile internet...
Here is the source code, where I establish the connection.
String urlString = "http://google.com";
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "ISO-8859-"));
String line = "";
while((line = reader.readLine()) != null){
line //do sthg with line
}
I hope that i gave enough information to you guys the help me to solve that problem
Regards
Maybe you could delete those
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);