Should BufferedInputStream be used when fetching bitmap data using HttpURLConnection? - android

I've read that wrapping a BufferedInputStream around an input stream is only of benefit if you're reading the input stream in small chunks. Otherwise, using it may actually have adverse effects.
What is the situation when the input stream is bitmap data fetched with HttpURLConnection (or your favourite networking library, e.g. OkHttp)... is it a help or a hindrance?
I'm wondering not only in terms of overall time/speed, but also in terms of resiliency... would using a buffer help at all with flaky network conditions where the connection is dropping in and out?
boolean useBufferedInputStream = true; // <--- true or false?
URL url = new URL("https://example.com/my_bitmap.png");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream inputStream;
if (useBufferedInputStream) {
inputStream = new BufferedInputStream(connection.getInputStream());
} else {
inputStream = connection.getInputStream();
}
Bitmap bmp = BitmapFactory.decodeStream(inputStream);

Related

Content length is not found in this URL

String thisurl ="http://songolum.com/file/ppdVkTxqhwcJu-CAzCgtNeICMi8mHZnKQBgnksb5o2Q/Ed%2BSheeran%2B-%2BPerfect.mp3?r=idz&dl=311&ref=ed-sheran-perfect";
url = null;
try {
url = new URL(thisurl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
// urlConnection.setRequestProperty("Transfer-Encoding", "chunked");
urlConnection.setRequestProperty("Accept-Encoding", "identity");
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
int l=0;
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
while(in.read()!=-1)
{
l=l+in.read();
}
System.out.println("Content-length" +l);
**I checked with other software and I found it's gzip compressed file and its with 10mb and I'm getting almost 1mb **
To answer your question directly, you were going wrong because you were calling read() twice, and also because you were adding together the values of each byte read, instead of counting them. InputStream.read() reads one byte and returns its value, or -1 on EOF. You need to read a number of bytes into a buffer and count how many bytes each read() call returned:
InputStream in = urlConnection.getInputStream();
byte[] buffer = new byte[4096];
int countBytesRead;
while((countBytesRead = in.read(buffer)) != -1) {
l += countBytesRead;
}
System.out.println("Content-length: " + l);
However, I suspect that this is not really what you need to do. The above code will simply return the size of all content in the response, including the HTTP headers and the content. Perhaps what you are looking for is the length of the document (or the file to be downloaded). You can use the Content-length HTTP header for that purpose (see other SO questions for how to get HTTP headers).
Also, note that the content may or may not be gzip-compressed. It depends on what the HTTP request says it accepts.
Please try this one hope so it will be helpful for you.
Using a HEAD request, i got my webserver to reply with the correct content-length field which otherwise was wrong. I don't know if this works in general but in my case it does:
private int tryGetFileSize(URL url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("HEAD");
conn.getInputStream();
return conn.getContentLength();
} catch (IOException e) {
return -1;
} finally {
conn.disconnect();
}
}

Load image from Google Places in Android

I'm having trouble with loading an image from a URL into my Android app using the Google Places API.
I got the part with the API working and I can see the image if I type the URL in my browser. The code fails in the below line:
Bitmap myBitmap = BitmapFactory.decodeStream(input);
The strange thing is, it simply jumps to the return null in the catch clause without executing the println commands.
I should also explain that I'm using two URL's since the first URL in the google API is a redirect page.
I assume that the problem is that the final page that's being loaded isn't actually a "real" image (I mean it looks like
https://lh4.googleusercontent.com/XXX/s1600-w400/
rather than something like
http://something/image.jpg)
Below is the entire method I'm using:
public Bitmap getImageData(Place p) {
try {
String src= "https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference="+
p.getPhoto_reference()+
"&key="+
this.context.getResources().getString(places_api);
Log.d("srcsrc", src);
URL url = new URL(src);
HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
ucon.setInstanceFollowRedirects(false);
URL secondURL = new URL(ucon.getHeaderField("Location"));
HttpsURLConnection connection = (HttpsURLConnection) secondURL.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Bitmap exception" + e);
return null;
}
}
Appreciate your help.
use Picasso like this :
Picasso.with(context).load(src).into(imageView );
It will do the following:
Handling ImageView recycling and download cancelation in an adapter.
Complex image transformations with minimal memory use.
Automatic memory and disk caching.

Making Sprite from image from web/server in AndEngine

I want to make a Sprite from an image which is placed on my server I have complete path of the image. Is it possible to do it in AndEngine.? Currently I am working in GLES 2.
first you need generate a link to your image and after,watch this code for load the image in a TextureRegion using HttpURLConnection and InputStream:
try {
ITexture mTexture = new BitmapTexture(pEngine.getTextureManager(), new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
URL url = new URL("https://yourImage.png");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
BufferedInputStream in = new BufferedInputStream(input);
return in;
}
});
mTexture.load();
TextureRegion MyImageFromWeb = TextureRegionFactory.extractFromTexture(mTexture);
} catch (IOException e) {
Debug.e(e);
}
it is possible you just have to download it first with HttpGet or UrlConnection in Background Thread
But i would recommend you to download all your assets in some kind of splash screen and saving them into sdcard

Making large REST requests

I have a REST service I can't alter, with methods for uploading an image, encoded as a Base64 string.
The problem is that the images can go up to sizes of 5-10MB, perhaps more. When I try to construct a Base64 representation of an image of this size on the device, I get an OutOfMemory exception.
I can however encode chunks of bytes at a time (3000 let's say), but this is useless as I would need the whole string to create a HttpGet/HttpPost object:
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("www.server.com/longString");
HttpResponse response = client.execute(httpGet);
Is there a way of going around this?
Edit: trying to use Heiko Rupp's suggestions + the android doc, I get an exception ("java.io.FileNotFoundException: http://www.google.com") at the following line: InputStream in = urlConnection.getInputStream();
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write("/translate".getBytes());
InputStream in = urlConnection.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
System.out.println("response:" + total);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Am I missing something? The GET request that I need to execute looks like this:
"http://myRESTService.com/myMethod?params=LOOONG-String", so the idea was to connect to http://myRESTService.com/myMethod and then output a few characters of the long string at a time. Is this correct?
You should try to use the URLConnection instead of the apache http client, as this does not require you to hold the object to send in memory, but instead you can do something like:
pseudocode!
HttpUrlConnection con = restUrl.getConnection();
while (!done) {
byte[] part = base64encode(partOfImage);
con.write (part);
partOfImage = nextPartOfImage();
}
con.flush();
con.close();
Also in Android after 2.2 Google recommends the URLConnection over the http client. See the description of DefaultHttpClient.
The other thing you may want to look into is the amount of data to be sent. 10 MB + base64 will take quite a while to transfer (even with gzip compression, which the URLConnection transparently enables if the server side accepts it) over a mobile network.
You must read docs for this REST service, no such service will require you to send such long data in GET. Images are always sent as POST. POST data is always at the end of request and allows to be added iteratively.

How to work with an image using url in android?

Given a Url for an image, I want to downoload it and paste it onto my canvas in android. How do I retrieve the image into my app ?
Please help.
Thanks,
de costo.
Dont forget to give the app the permission to connect to the Web,
in the AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
You can use the following code to download an image:
URLConnection connection = uri.toURL().openConnection();
connection.connect();
InputStream is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 8 * 1024);
Bitmap bmp = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
Requires the following permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
There is a an HTTP client library that might be supported in Android now, but for any fine grain control you can use URL & HttpURLConnection. the code will look something like this:
URL connectURL = new URL(<your URL goes here>);
HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
// do some setup
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("GET");
// connect and flush the request out
conn.connect();
conn.getOutputStream().flush();
// now fetch the results
String response = getResponse(conn);
where getResponse() looks something like this, in your case you are getting
a pile of binary data back you might want to change the StringBuffer to a byte array
and chunk the reads by a larger increment.
private String getResponseOrig(HttpURLConnection conn)
{
InputStream is = null;
try
{
is = conn.getInputStream();
// scoop up the reply from the server
int ch;
StringBuffer sb = new StringBuffer();
while( ( ch = is.read() ) != -1 ) {
sb.append( (char)ch );
}
return sb.toString();
}
catch(Exception e)
{
Log.e(TAG, "biffed it getting HTTPResponse");
}
finally
{
try {
if (is != null)
is.close();
} catch (Exception e) {}
}
return "";
}
As you are talking about image data which can be large, other things you need to be assiduous about in Android is making sure you release your memory as soon as you can, you've only got 16mb of heap to play with for all apps and it runs out fast and the GC will drive you nuts if you aren't really good about giving back memory resources

Categories

Resources