Edit: The thing causing the error was a typo in the url variable declaration. The code provided works, given correct input. See my answer for details.
Original Question: I'm working on an application that regularly sends a GET request to a certain web server.
I have tried and verified the URL and the query in the browser and I get the information in XML format as expected.
The URL/query looks like this:
http://foo.bar.com:8080/bla/ha/get_stuff?param1=gargle¶m2=blurp
I'm trying to get the raw content to my device (Android tablet) and output it to the screen.
However, when calling getInputStream() on my URLConnection object, I get the following exception:
java.net.ProtocolException: Unexpected status line: SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1
Calling connect() on the same object causes no exception (however other methods, such as getContent(), do).
getContentType() returns null.
I'm using AsyncTask to collect and display the data (displaying works fine).
In the code is also an Authenticator part, but removing it has no change on the exception thrown, so I don't think it's the issue.
Is this because the data is in XML format?
If so, how else should I access it?
Code
class GetPositionTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String url = "http://foo.bar.com/8080/bla/ha/get_stuff";
String charset = "UTF-8";
String param1 = "gargle";
String param2 = "blurp";
try {
String query = String.format("param1=%s¶m2=%s",
URLEncoder.encode(param1, charset),
URLEncoder.encode(param2, charset));
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("userName", "passWord".toCharArray());
}
});
URLConnection urlConnection = new URL(url + "?" + query).openConnection();
urlConnection.setRequestProperty("Accept-Charset", charset);
InputStream response = urlConnection.getInputStream(); //Commenting this out prevents exception
return "Made it through!"; // Never reaches this
}
catch (IOException e) {
e.printStackTrace();
return "Exception in GetPositionTask";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(s);
}
}
Note: This is similar to a couple of other questions, however I wasn't able to solve my problem reading those.
The cause was a simple type in the url string, which was supposed to be
String url = "http://foo.bar.com:8080/bla/ha/get_stuff";
rather than
String url = "http://foo.bar.com/8080/bla/ha/get_stuff";
Fixing that typo made the whole thing work as a charm.
Interestingly though, when I circumvented the whole concatenation and formatting business by pasting the complete URL/query into the URLconstructor as below, it still worked (even though the URLEncoder#encode calls did switch some :characters out in param2).
URLConnection urlConnection = new URL("http://foo.bar.com:8080/bla/ha/get_stuff?param1=gurgle¶m2=blurp").openConnection();
(in my real case, the param2 variable includes a MAC address, and the :'s were replaced with something of the type %xx)
You're connecting to an SSH server, not an HTTP server.
The reason it doesn't happen on connect() is that connect() doesn't actually connect. The other methods you mention do, if necessary.
Related
I am given a shortened url and I want to get the expanded form. The below java function is used to achieve this.
public String expand(String shortenedUrl){
URL url = null;
try {
url = new URL(shortenedUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
// open connection
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
} catch (IOException e) {
e.printStackTrace();
}
// stop following browser redirect
httpURLConnection.setInstanceFollowRedirects(false);
// extract location header containing the actual destination URL
String expandedURL = httpURLConnection.getHeaderField("Location");
httpURLConnection.disconnect();
return expandedURL;
}
The code works fine in Eclipse but the same doesn't work in android.
String expandedURL = httpURLConnection.getHeaderField("Location");
The above line throws java.lang.RuntimeException: Unable to start activity ComponentInfo. And the error is pointed to the above line. If I remove the above line no error is encountered. Even I am not able to use getResponseCode() function.
int status = 0;
try {
status = httpURLConnection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
This piece of code also has the same problem. works in eclipse but not in android.
Any kind of help will be greatly appreciated.
Edit: The code using above function is,
ExpandUrl expandUrl = new ExpandUrl();
String expandedUrl = expandUrl.expand(shortenedUrl);
Note: The function expand is defined inside the class ExpandUrl.
Well, the code works in Eclipse but not in android. The reason is that you are doing it in Main thread and blocking it. Android wouldn't allow you to do so and throw runtime error.
I have tried to implement your code using AsyncTask in android. It works fine.
Give it a try.
To know more about AsyncTask follow: Android Documentation on AsyncTask
Good Luck!
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 8 years ago.
I know this question has been asked a lot on SO already so I apologize if it is redundant, but I can't seem to find an answer to my specific problem anywhere.
I'm attempting to connect my Android emulator to a localhost. Here is my connection code:
public void readPHP(String filename) throws IOException {
url = new URL("http://10.0.2.2:8000/" + filename);
URLConnection conn = url.openConnection();
InputStream stream = null;
try {
stream = conn.getInputStream();
} catch (IOException e) {
System.out.println(e.getMessage());
}
// more code....
stream.close();
}
I've also added the following line to my manifesto:
<uses-permission android:name="android.permission.INTERNET"/>
The app installs properly with no error messages but when I try to run it from the phone, it crashes with the vague message "Unfortunately, CodeGlass GDK has stopped." I'm sure this is a problem with Android because when I try to run the same code in a simple Java program it works as expected.
You are opening a connection in your UI Thread, which is causing an NetworkOnMainThreadException . Just put your code inside an AsyncTask, inside doInBackground() method, like this:
public class MyAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(String fileName) {
url = new URL("http://10.0.2.2:8000/" + filename);
URLConnection conn = url.openConnection();
InputStream stream = null;
try {
stream = conn.getInputStream();
} catch (IOException e) {
System.out.println(e.getMessage());
}
// more code....
stream.close();
return null;
}
}
You must use asynctask to get the data from url like they said.
But there is another way. İt is not advisable normally, but if you want to move on for now and get back and properly write an asynctask, you can use this piece of code for now;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Hope this helps.
I am taking some data from a database via a servlet and a db handler java class and hosting it at a url. Since the database is changing I'm taking care only to host the changes rather than the entire db data.
I'm getting the required functionality by a browser i.e after every (manual) reload, I'm getting the data as required by me,
1. at the first page load, entire data gets displayed.
2. at subsequent reloads, I get either null data if there is no change in the database, or the appended rows if the database extends. (the database can only extend).
But then in a java program, I'm not getting the same functionality. The java program using HttpUrlConnection.
This is the code for the java client for servlet...
public class HTTPClient implements Runnable {
private CallbackInterface callbackinterface;
private URL url;
private HttpURLConnection http;
private InputStream response;
private String previousMessage = "";
public HTTPClient() {
try {
url = new URL("http://localhost:8080/RESTful-Server/index.jsp");
http = (HttpURLConnection) url.openConnection();
http.connect();
} catch (IOException e) {
}
}
#Override
public void run() {
while (true) {
try {
String currentmessage = "";
response = http.getInputStream();
if (http.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader buffread = new BufferedReader(new InputStreamReader(response));
String line;
for (; (line = buffread.readLine()) != null;) {
currentmessage += line;
}
if ((!currentmessage.equals(previousMessage)
|| !previousMessage.equals(""))
&& !currentmessage.equals("")) {
//this.callbackinterface.event(currentmessage);\
System.out.println(currentmessage + "\t" + previousMessage);
}
previousMessage = currentmessage;
Thread.sleep(2500);
} else {
throw new IOException();
}
} catch (IOException | InterruptedException e) {
System.err.println("Exception" + e);
}
}
}
The shown class is a thread which read the connections every 2.5 s. If it gets something significant in the getline(), it will issue a callback to a worker method, which takes care of remaining things.
I am thinking the issues is because of the class variable conn, and that reload as in the browser is not getting replicated..
Any idea how to do this?
You're basically connecting (requesting) only once and trying to read the response multiple times, while it can be read only once. You basically need to create a new connection (request) everytime. You need to move the creation of the connection by url.openConnection() to inside the loop. The line http.connect() is by the way superfluous. You can safely omit it. The http.getInputStream() will already implicitly do it.
See also:
Using java.net.URLConnection to fire and handle HTTP requests
After reading: Getting the 'external' IP address in Java
code:
public static void main(String[] args) throws IOException
{
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
}
I thought I was a winner but I get the following error
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: http://automation.whatismyip.com/n09230945.asp
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at getIP.main(getIP.java:12)
I think this is because the server isnt responding quick enough, is there anyway to ensure that it will get the external ip?
EDIT: okay so its getting rejected, anyone else know of another site that can do the same function
public static void main(String[] args) throws IOException
{
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection();
String str = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
str = reader.readLine();
System.out.println(str);
}
Before you run the following code take a look at this: http://www.whatismyip.com/faq/automation.asp
public static void main(String[] args) throws Exception {
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
URLConnection connection = whatismyip.openConnection();
connection.addRequestProperty("Protocol", "Http/1.1");
connection.addRequestProperty("Connection", "keep-alive");
connection.addRequestProperty("Keep-Alive", "1000");
connection.addRequestProperty("User-Agent", "Web-Agent");
BufferedReader in =
new BufferedReader(new InputStreamReader(connection.getInputStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
}
While playing with Go I saw your question. I made a quick App on Google App Engine using Go:
Hit this URL:
http://agentgatech.appspot.com/
Java code:
new BufferedReader(new InputStreamReader(new URL('http://agentgatech.appspot.com').openStream())).readLine()
Go code for the app which you can copy and make your own app:
package hello
import (
"fmt"
"net/http"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, r.RemoteAddr)
}
Some servers has triggers that blocks access from "non-browsers". They understand that you are some kind of automatic app that can do a DOS attack. To avoid this, you can try to use a lib to access the resource and set the "browser" header.
wget works in this way:
wget -r -p -U Mozilla http://www.site.com/resource.html
Using Java, you can use the HttpClient lib and set the "User-Agent" header.
Look the topic 5 of "Things To Try" section.
Hope this can help you.
A 403 response indicates that the server is explicitly rejecting your request for some reason. Contact the operator of WhatIsMyIP for details.
We've set up CloudFlare and as designed they're challenging unfamiliar useragents. If you can set your UA to something common, you should be able to gain access.
You can use another web service like this; http://freegeoip.net/static/index.html
Using the Check IP address link on AWS worked for me.Please note that MalformedURLException,IOException are to be added as well
public String getPublicIpAddress() throws MalformedURLException,IOException {
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection();
String str = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
str = reader.readLine();
return str;
}
This is how I do it with rxJava2 and Butterknife. You'll want to run the networking code in another thread because you'll get an exception for running network code on the main thread!
I use rxJava instead of AsyncTask because the rxJava cleans up nicely when the user moves on to the next UI before the thread is finished. (this is super useful for very busy UI's)
public class ConfigurationActivity extends AppCompatActivity {
// VIEWS
#BindView(R.id.externalip) TextInputEditText externalIp;//this could be TextView, etc.
// rxJava - note: I have this line in the base class - for demo purposes it's here
private CompositeDisposable compositeSubscription = new CompositeDisposable();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_wonderful_layout);
ButterKnife.bind(this);
getExternalIpAsync();
}
// note: I have this code in the base class - for demo purposes it's here
#Override
protected void onStop() {
super.onStop();
clearRxSubscriptions();
}
// note: I have this code in the base class - for demo purposes it's here
protected void addRxSubscription(Disposable subscription) {
if (compositeSubscription != null) compositeSubscription.add(subscription);
}
// note: I have this code in the base class - for demo purposes it's here
private void clearRxSubscriptions() {
if (compositeSubscription != null) compositeSubscription.clear();
}
private void getExternalIpAsync() {
addRxSubscription(
Observable.just("")
.map(s -> getExternalIp())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((String ip) -> {
if (ip != null) {
externalIp.setText(ip);
}
})
);
}
private String getExternalIp() {
String externIp = null;
try {
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection(Proxy.NO_PROXY);
con.setConnectTimeout(1000);//low value for quicker result (otherwise takes about 20secs)
con.setReadTimeout(5000);
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
externIp = reader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
return externIp;
}
}
UPDATE - I've found that URLConnection is really quite shit; it'll take a long time to get a result, not really time out very well, etc. The code below improves the situation with OKhttp
private String getExternalIp() {
String externIp = "no connection";
OkHttpClient client = new OkHttpClient();//should have this as a member variable
try {
String url = "http://checkip.amazonaws.com/";
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
if (responseBody != null) externIp = responseBody.string();
} catch (IOException e) {
e.printStackTrace();
}
return externIp;
}
I am doing HTTP POSTs very frequently (>= 1/sec) to an API endpoint and I want to make sure I'm doing it efficiently. My goal is to succeed or fail as soon as possible, especially since I have separate code to retry failed POSTs. There is a nice page of HttpClient performance tips, but I'm not sure if exhaustively implementing them all will have real benefits. Here is my code right now:
public class Poster {
private String url;
// re-use our request
private HttpClient client;
// re-use our method
private PostMethod method;
public Poster(String url) {
this.url = url;
// Set up the request for reuse.
HttpClientParams clientParams = new HttpClientParams();
clientParams.setSoTimeout(1000); // 1 second timeout.
this.client = new HttpClient(clientParams);
// don't check for stale connections, since we want to be as fast as possible?
// this.client.getParams().setParameter("http.connection.stalecheck", false);
this.method = new PostMethod(this.url);
// custom RetryHandler to prevent retry attempts
HttpMethodRetryHandler myretryhandler = new HttpMethodRetryHandler() {
public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) {
// For now, never retry
return false;
}
};
this.method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
}
protected boolean sendData(SensorData data) {
NameValuePair[] payload = {
// ...
};
method.setRequestBody(payload);
// Execute it and get the results.
try {
// Execute the POST method.
client.executeMethod(method);
} catch (IOException e) {
// unable to POST, deal with consequences here
method.releaseConnection();
return false;
}
// don't release so that it can be reused?
method.releaseConnection();
return method.getStatusCode() == HttpStatus.SC_OK;
}
}
Would it make sense to disable the check for stale connections? Should I be looking at using the MultiThreadedConnectionManager? Of course, actual benchmarking would help but I wanted to check if my code is on the right track first.
Much of the performance hit of http connections is establishing the socket connection. You can avoid this by using 'keep-alive' http connections. To do this, it's best to use HTTP 1.1 and make sure that "Content-Length: xx" is always set in requests and responses, "Connecction: close" is correctly set when appropriate and is properly acted upon when received.