Until recently, I decoded images from a web resource using the Apache HTTP Client using this code:
HttpGet httpRequest = new HttpGet(params[0].toURI());
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufferedEntity = new BufferedHttpEntity(entity);
return BitmapFactory.decodeStream(bufferedEntity.getContent());
This all worked perfectly fine.
Now with Android 6, Apache HTTP Client has been deprecated. Not to worry, I thought, just use java.net.HttpUrlConnection instead as recommended here:
http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
The code I tried and that I found in other questions here is:
HttpURLConnection connection = (HttpURLConnection) params[0].openConnection();
// connection.setRequestProperty("User-Agent", "");
connection.setRequestMethod("GET");
// connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
return bitmap;
This doesn't work. bitmap will always be null for the same image resource that works with the old code.
Does anyone have any insight into this? Here are other questions I tried and why they didn't work:
Android: bitmapfactory.decodestream returns null (Answers use deprecated methods/classes)
Bitmap.decodeStream returns null on specific existing (And working) images (Same as above)
The problem was caused by a simple HTTP/HTTPS issue. The image resource was requested from a http:// address. The server is set up to issue a 307 (temporary redirect) to the matching https:// address.
Although the default of HttpURLConnection is to follow redirects, the code given in the question didn't work. FYI Picasso didn't load the image either.
Requesting the image via its https:// address solved the problem.
Use Volley or Picasso. That's the recommended approach.
Related
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.
This question already has an answer here:
JSONParser from androidhive tutorial, NoSuchMethodError in DefaultHttpClient
(1 answer)
Closed 7 years ago.
I've been searching a lot, however haven't find any solution. I want to use URL, HttpsUrlConnection instead of deprecated ones (HttpClient, HttpPost, DefaultHttpClient). I have this code below so far:
Note "MyUrl" takes some parameters. See question 2.
URL url = new URL("MyUrl");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
/*Here exception occurs!*/
connection.connect();
So, I have 2 problems to solve: (Maybe the 2nd one should be solved 1stly. I have no idea...)
When I use connection.someMethod(); SSLException occurs. (i.e connection.getResponseCode();)
The Error is :
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x635cb550: Failure in SSL library, usually a protocol error
What is alternative way of List<NameValuePair> & BasicNameValuePair ? Those are deprecated as well.
You can use following library for HTTP requests-response
http://loopj.com/android-async-http/
http://square.github.io/okhttp/
http://developer.android.com/training/volley/index.html
You can use Google-Gson for parsing JSON data
https://github.com/google/gson
You don't need to use connect. Simply doing this:
conn.setRequestMethod("POST");
InputStream in = new BufferedInputStream(conn.getInputStream());
response = org.apache.commons.io.IOUtils.toString(in, "UTF-8");
You will get your response.
Also, you can use ContentValues as a replacement for NameValuePair:
ContentValues initialValues = new ContentValues();
initialValues.put("parameter", value);
I'm trying to PUT some XML to a server, but the gist of it is that no matter what I do, HttpPut simply won't put anything in the Http body. The server always comes back saying that the body is missing, and looking at it through Wireshark, nothing is there! Here's the code I'm using to set up and run the request:
HttpPut putRequest = new HttpPut(urlString]);
StringEntity stringEntity = new StringEntity(xmlString, HTTP.ISO_8859_1);
stringEntity.setContentType("text/xml");
putRequest.setEntity(stringEntity);
putRequest.addHeader("Host", formatUrlForHostHeader(broadsoftUrl));
putRequest.addHeader("Authorization", authorizationString);
putRequest.addHeader("Content-Type", "text/xml");
putRequest.addHeader("Accept", "text/xml");
response = httpClient.execute(putRequest);
I'm not sure what else to include here. I tried it on 4.2 and 4.0.3. This code is running in the doInBackground of an AsyncTask. The response code I get is a 409 Conflict, and the body is the server's application-specific message, telling me the body is missing. I confirmed that it's missing with Wireshark.
EDIT:
An interesting note is that I ran the same code standalone on my desktop, and it worked. So, is there something up with the Android versions of HttpClient, or the system? I tried a few different API levels, too, just to check.
Any thoughts?
Thanks!
Alright, so the solution was to just give up on HttpPut and all that, and use HttpURLConnection. Here's how we ended up doing it:
URL url = new URL(theUrl);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setRequestProperty("Host", formatUrlForHostHeader(broadsoftUrl));
httpCon.setRequestProperty("Authorization", authorizationString);
httpCon.setRequestProperty("Content-Type", "text/xml; charset=ISO_8859_1");
httpCon.setRequestProperty("Accept", "text/xml");
httpCon.setDoInput(true);
httpCon.setDoOutput(true);
httpCon.setRequestMethod("PUT");
OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream(), "ISO_8859_1");
out.write(xmlData);
out.close();
if(httpCon.getErrorStream() == null) {
return "";
} else {
return "ERROR";
}
We didn't need to get the response from our PUT request, but you check if it failed by seeing if the error stream exists. If you wanted to get the response, you would do something like this:
StringWriter writer = new StringWriter();
IOUtils.copy(httpCon.getInputStream(), writer, encoding);
String responseString = writer.toString();
Of course, you would have to include Apache's IOTools in your app.
409 Conflict is usually an Edit Conflict error, usually associated with wikis, but it could be any type of conflict with the request.
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
What type of data are you trying to post and is it possible that the host has existing data that cannot be changed?
I want to get the header information from a webservice call. That service returns a image but need to also get the header information. For getting the image I simply pass inputstream to decodeStream method. How can one get the headers too from that?
Regards
Sunil
Look at the code that does HTTP requests. Perhaps it's something along the lines of
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
return is;
(error handling and other details omitted in this snippet). Look up HttpResponse documentation, its getFirstHeader method is your friend!
If you're using a URLConnection to get your InputStream then yes, the same was as you would do it in standard Java. URLConnection has a method called getHeaderFieldKey(int) and another called getHeaderFields().
Example here.
Android URLConnection docs here
This is how my programme works:
1) Display a picture from the server
2) User change the picture and upload it to the server
3) Display the picture by re-downloading from the server
This is how I get the picture from the server:
String src = "http://www.getyourpicture.com/mypicture.jpg"
HttpGet httpRequest = new HttpGet(URI.create(src) );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse)httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
Bitmap dp = BitmapFactory.decodeStream(instream);
//display dp from here...
The problem here is, whenever I "re-download" the image, it still shows the old picture.
To confirm that I've uploaded the picture, I've checked the folder containing the picture on the server and even visited the link on a browser. Both approaches show that the picture is indeed been uploaded. So I've narrowed down to the possibility that Android might have a http caching manager that is not "refreshing" the image link.
So, if the answer to my question is "yes", how can I force the application to not use the cache?
If the answer is "no", what is the thing that I've overlooked?
I'm not sure about the undercovers working and the defaults of HTTP request caching on Android, but if it is decent, then it should in theory suffice to add a query string with a timestamp to the request URL to trigger a brand new and fullworthy HTTP request.
String src = "http://www.getyourpicture.com/mypicture.jpg?" + System.currentTimeMillis();