I'm about to code an Android app (using A.Studio 3.5.1) that should connect to a back-end using https. I'm quite new to the techniques so I looked at https://developer.android.com/training/articles/security-ssl.html#HttpsExample
I has four lines of code:
URL url = new URL("https://wikipedia.org");
URLConnection urlConnection = url.openConnection();
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
When I try it I get a red text;
new URL gives MalformedURLException
url.openConnection() gives IOException,
urlConnection.getInputStream() also
copyInputStreamToOutputStream is not found.
I have read about copyInputStreamToOutputStream, that it can be solved
copyInputStreamToOutputStream(in, System.out)
and
Easy way to write contents of a Java InputStream to an OutputStream
I tried the first way, using apache commons, with no success.
I'm mostly curious about the exceptions.
I will try another walk-through on
https://codelabs.developers.google.com/codelabs/android-network-security-config/
But it would be nice to learn about this...
I have faced similar situations many times. This occur because the webpage you are trying to reach doesn't return anything as a response after connection is established. So the parsing returns IOException as there is nothing to read in the response of URL after connection.
newURL is returning MalformedURLException because your url contains -- " -- which should be escaped as these are special characters.
Hope this helps.
Related
How can I receive Pushbullet notes/images/profile details via API-Key on Android? My main problem is the SSL security in that point. (BTW: I'm pretty much a beginner in Android and only know the basics.)
The auth looks like this:
https://apikey#api.pushbullet.com/v2/users/me
I'm successfully requesting the content of a webpage (e.g. wikipedia.org) via
try {
URL url = new URL("https://www.wikipedia.org");
URLConnection urlConnection = url.openConnection();
InputStream in = urlConnection.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer);
theString = writer.toString();
textView.setText(theString);
} catch (Exception e) {
textView.setText("Error: "+e "String content: " +theString);
}
but when I'm requesting, for example, my profile details I'm always getting a
javaio FileNotFoundException
If you run your requests through https://www.runscope.com you can often see what the request is that your client is actually making (they have a free plan for trying it out).
If I had to guess I would say it's likely the authorization is not working correctly. Are you able to get that page using curl? It should look something like:
curl -u <apikey>: https://api.pushbullet.com/v2/users/me
Assuming that works, try something like
urlConnection.setRequestProperty("Authorization", "Bearer <apikey>");
or however it is you set headers on your HTTP requests. This is more explicit than relying on the https://password#domain url thing.
I'm Unable to download file from FTP server using URLConnection having spaces in pat
String s = "ftp://username:password#ftpclient:21/AAB BBC/hhhh 0001.jpg";
URL u = new URL(s);
URLConnection uc = u.openConnection();
BufferedOutputStream bos = new BufferedOutputStream(uc.getOutputStream());
Dont want FTP client solution.
Using URLencoder getting 550 error file not found.
Thanks,
Gaurav
Are you using Apache commons Library ? If so , use this code
try {
FileOutputStream desFileStream = new FileOutputStream(desFilePath);;
status = FTP_object.retrieveFile(srcFilePath, desFileStream);
desFileStream.close();
return status;
} catch (Exception e) {
Log.d(TAG, "download failed");
}
You shouldn't have spaces in your URL itself per RFC1738 section 2.2 Run it through the URL Encode method to encode it:
String s = "ftp://username:password#ftpclient:21/AAB BBC/hhhh 0001.jpg";
String encodedUrl = URLEncoder.encode(s,"UTF-8");
I realize you said you were already doing the encoding, but that returned a 550 error. I didn't see the encoding so am just mentioning it should be needed.
I would really try this from a browser and see if you can get to it. I would also dump out the URL it is using and try that from a browser (or wget, curl, whatever you have handy). The 550 is listed as being a "permission" problem, not file not found, so I'm a little surprised at that, but that may be the short code and come up as an error to prevent people from poking around testing user/password combinations. Hard to say.
The other question I have for you is that you mention you don't want a client solution, but you seem to be writing a client not a server. You're going to port 21, which is the default FTP port for a server.
I would try various combinations of the encoding and see if maybe you're not encoding everything...you should encode the url path. Does the password have any funky characters in it?
Testing from the browser directly will give you a lot of insight.
I have an Android app that works fine with Android 2.x and 3.x, but it fails when run on Android 4.x.
The problem is in this section of code:
URL url = new URL("http://blahblah.blah/somedata.xml");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
When the application is running on Android 4.x, the getInputStream() call results in a FileNotFoundException. When the same binary is running on earlier versions of Android, it succeeds. The URLs also work fine in web browsers and with curl.
Apparently something about HttpURLConnection has changed in ICS. Does anybody have any idea what has changed, and/or what the fix might be?
Try removing the setDoOutput call. Taken from this blog:
a blog
Edit: This is needed when using a POST call.
A FileNotFoundException may also been thrown if the server returns a bad error code (e.g., 400 or 401). You can handle this as follows:
int responseCode = con.getResponseCode(); //can call this instead of con.connect()
if (responseCode >= 400 && responseCode <= 499) {
throw new Exception("Bad authentication status: " + responseCode); //provide a more meaningful exception message
}
else {
InputStream in = con.getInputStream();
//etc...
}
I Don't know why, but dealing manually with redirection resolves the problem.
connection.setInstanceFollowRedirects(false);
A little late but you can also verify the accepted content. You can add this line to accept all kinds of contents
urlConnection.setRequestProperty("Accept","*/*");
I have the following code to read a website. The code is searches on google. I want to open automatically the first result and read it again. For the keywords i want the "I am feeling lucky is not working". Please somebody help me find a solution
I have the following code.
URL url = new URL("http://www.google.com/search?q=sample");
URLConnection urlConnection = url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
try {
readStream(in);
finally {
in.close();
}
}
The query sample is just a sample....
Its already discussed in SO QA :
How to search in google by using java code?
Your approach is also a solution. But it will be complex as it requires parsing of returned HTML.
I think there are some APIS for doing this.
http://code.google.com/p/google-api-java-client/
This is deprecated but might still work -->
http://code.google.com/apis/websearch/docs/
In my browser, or in iOS, when I try to get the contents of a URL with encoded http authentication information in the form
http://myUser:myPassword#www.example.com/secure/area/index.html
It just works. I'm getting URLs from a web service, and I'd like to avoid trying to parse them up for their HTTP auth info if I can help it. Is there a way to do something similar in Android without actually parsing the URLs? Alternatively, what is the best way to go about that?
UPDATE:
I find that when I try to set the authentication information in an Authorization header, I get a very strange FileNotFoundException.
Here's the code I'm using:
URL url = new URL(urlString);
URLConnection connection;
String authority = url.getAuthority();
if (authority.contains("#")) {
String userPasswordString = authority.split("#")[0];
url = new URL(urlString.replace(userPasswordString + "#", ""));
connection = url.openConnection();
String encoded = new String(Base64.encode(userPasswordString.getBytes(), Base64.DEFAULT), "UTF-8");
connection.setRequestProperty("Authorization", "Basic " + encoded);
} else {
connection = url.openConnection();
}
InputStream responseStream = connection.getInputStream();
All the info seems to check out, I've verified the url is correct, the base64 string is correct, and the file is certainly on the server--I have no trouble at all opening it with Firefox, and Firebug shows all the right headers, matching what I've sent as far as I can tell. What I get though is the following error (url host changed to protect the innocent):
java.io.FileNotFoundException: http://a1b.example.com/grid/uploads/profile/avatar/user1/custom-avatar.jpg
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1061)
Any idea what this is all about?
I looked into using HttpClient, but saw that in Issue 16041 it is recommended that we prefer URLConnection.
That looks like your browser is applying some extra rules to parsing the URL. In Android you can use HTTP Client's authentication mechanism such as BASIC and DIGEST to do the same things. Which one you choose is dependent on the server you are trying to authenticate against.
Here is a good page to get you started.
Unfortunately, on Android you can't pass the user info (username/password) in that format to either java.net.URL or HttpClient and have it work like in a browser.
I'd recommend using URI (see http://download.oracle.com/javase/1.5.0/docs/api/index.html?java/net/URI.html) to do this: pass your URL to the URI constructor that takes a String and then you can extract the user info (using getUserInfo()). You can then either use HttpClient's authorization classes (see http://developer.android.com/reference/org/apache/http/auth/package-summary.html) or build the basic auth header yourself (an example is given at http://www.avajava.com/tutorials/lessons/how-do-i-connect-to-a-url-using-basic-authentication.html).