Best way to download remote images without third party libraries? - java

Welcome
I need to download sycnronously (one at time) a lot of small remote images (between 50kb and 100kb) from a server and to store them as PNG in the device. I need to achieve this without third party libraries and I'm using this code but it is too munch slow:
URL javaUrl = new URL(URLParser.parse(this.url));
URLConnection connection = javaUrl.openConnection();
InputStream input = new BufferedInputStream(javaUrl.openStream());
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
// conversion to bitmap
InputStream in = new ByteArrayInputStream(output.toByteArray());
Bitmap original = BitmapFactory.decodeStream(in);
// storing bitmap as PNG file
FileOutputStream out = new FileOutputStream(filename);
original.compress(Bitmap.CompressFormat.PNG, 90, out);
output.flush();
output.close();
input.close();
in.close();
original.recycle();
The problem is that the download is very slow. With very fast WIFI internet in the device (13MB, download speed of 1.4mbytes/s), it is taking 3-4 seconds to download the image in the device, but only 100-200ms to download the image in my PC using google chrome for example.
It is something wrong in my download algorithm? can be improved?
Thanks

You have a totally unnecessary byte array in the middle.
BitmapFactory.decodeStream() accepts an InputStream and you get an InputStream from URL.openStream().
It might not give you the speed boost you're looking for, but it'll at least get rid of a completely useless step in your code.

Related

faster wifi file transfer between android devices?

I am working with a android application in which I am wanting to share the file from one device to another through Wi-Fi. I am getting the speed of around 1.5 Mega Byte/s. Is there any way by which I can transfer the file by much higher data rate?
Can you please tell why we are getting this less data rate even the devices and router is capable of handling more than 150Mbps (18.75MBps) data rate...
Is it possible to use UFTP and will it be solving the purpose??
here is the code :
byte[] buf = new byte[2048];
try {
int bytesRead = 0;
while ((bytesRead = dis.read(buf, 0, buf.length)) != -1) {
fLength = fLength - bytesRead;
dos.write(buf, 0, bytesRead);
Log.i("File Tranfer Thread", String.valueOf(fLength) + Thread.currentThread().getName());
}
}
}
Thanks
Your code is fast.
There one thing you can try that worth the cost is playing with packet size. Try to modify the pack size in order to see the faster solution. Sometimes bigger packet is faster to send.
packet size bigger byte[] buf = new byte[2048*10];
packet size smaller byte[] buf = new byte[512];
packet size 3 byte[] buf = new byte[2048*5];

Faster way for Bitmap to Byte[] coversion

I am not new to bitmaps nor new to java. I am trying to convert High resolution bitmaps to byte array in a loop. Please find code here:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
imageByteArray = stream.toByteArray();
When i am using the above approach I cam able to convert 5 images in 1 second. But I need it to be even faster. I tried ByteBuffer approach also like this:
Bitmap bmp = intent.getExtras().get("data");
int size = bmp.getRowBytes() * bmp.getHeight();
ByteBuffer b = ByteBuffer.allocate(size);
bmp.copyPixelsToBuffer(b);
byte[] bytes = new byte[size];
try {
b.get(bytes, 0, bytes.length);
} catch (BufferUnderflowException e) {
// always happens
}
But this is very slow (Slower then previous) :(
Please, can somebody give a faster method? Guide Me...
The first solution is the right one.
But two things can happen here:
The image is maybe not of JPEG type, so conversion occurs, which takes time
The image is compressed 50%, which takes time
That aside, if it's taking some time, I doubt it could go faster (being the right solution).
You must consider the fact that the speed of processing is tightly tied to the speed of the device you are testing on( since this is tagged android I'm presuming you're using a mobile device ).
You should take a look at android developer on how to handle large bitmaps effectively Android developers . Since processing 5 high resolution images per second is slow to you I can presume you are having some kind of gallery or previews? If that's the case you shouldn't handle the high resolution images and should indeed take a look at the link above.
Also as a side-note your second code can be optimised this way:
int bytes = bmp.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bmp.copyPixelsToBuffer(buffer);
byte[] array = buffer.array();
Otherwise the most efficient way of copying bytes that I know is copy() taken from Commons-IO:
public static int copy(InputStream input, OutputStream output) throws IOException {
int n, count = 0;
byte[] buffer = new byte[4 * 1024];
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
you can try as follows
Bitmap bitmap = intent.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap .compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
hope it may work good for you!!
check for line bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream); it may cause problem..as you are using JPEG format with rate 50.

InputStream to receive files twice explicitly [duplicate]

This question already has an answer here:
Receiving multiple images over TCP socket using InputStream
(1 answer)
Closed 9 years ago.
I am trying to send two images with a difference of 5 seconds between them from an android phone (client) to PC(server).
I am using InputStream to do this for me.
ServerSocket servsock = new ServerSocket(27508);
Socket sock = servsock.accept();
System.out.println("connection accepted ");
int count;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
InputStream is = null;
is = sock.getInputStream();
int bufferSize = sock.getReceiveBufferSize();
byte[] bytes = new byte[bufferSize];
System.out.println("Here1");
fos = new FileOutputStream("D:\\fypimages\\image" + imgNum + ".jpeg");
bos = new BufferedOutputStream(fos);
imgNum++;
while ((count = is.read(bytes)) > 0)
{
bos.write(bytes, 0, count);
System.out.println("count: " + count);
}
bos.flush();
bytes = new byte[bufferSize];
System.out.println("Here2");
fos = new FileOutputStream("D:\\fypimages\\image" + imgNum + ".jpeg");
bos = new BufferedOutputStream(fos);
imgNum++;
while ((count = is.read(bytes)) > 0)
{
bos.write(bytes, 0, count);
System.out.println("count: " + count);
}
bos.flush();
System.out.println("Here3");
The problem is is.read(bytes) blocks the code only for the first image and then the program is terminated and it does not block for the second image.
I know it returns -1 when the first image is recieved completely, but how do I make it work for the second time ?
If read returns -1, it means other side closed the connection. But your basic problem seems to be, you're not handling the connection as stream. In a data stream, there are no inherent "packages", in this case no built-in way to distinguish one image from next.
You can proceed in at least 3 different ways:
Add your own simple protocol, for example: at sending side, write number of bytes in image, then write image bytes, then write number of bytes in next image, then write next image, etc, without closing the connection. And at receiving side, loop first reading the number of bytes, then reading that many bytes of image data.
Write one image per connection, then close the connection and create new connection for next image.
In this case, because data is JPEG images, just write all JPEG images as one data stream, then on receiving side, parse the JPEG format to see where the image boundaries are.
First choice is most efficient, and also is easily extended to deliver image name or other extra data in addition to image file length. Second is ok, and most simple and robust (for example, no need to worry about byte order, or worry about getting out of sync between sender and receiver), if there aren't too many images, but if there are hundreds of images, then re-connecting is going to slow things down a bit. Third choice is probably not the way to go with JPEGs, just listed is as a possiblity.

Very slow download speeds with this code, any help improving it?

in my Android app I need to download a ~40 MB file, and I'm testing the code in my phone but the download speed is REALLY slow, I tried to download from different sources that are fast when using my PC.
Here is the code I use in the download service:
URLConnection conexion;
URL url;
int lenghtOfFile = 0;
try {
url = new URL("<URL>");
conexion = url.openConnection();
conexion.connect();
lenghtOfFile = conexion.getContentLength();
try {
File f = new File(Environment.getExternalStorageDirectory() + "/testing");
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(f.getAbsolutePath());
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
notification.contentView.setProgressBar(R.id.status_progress, 100, (int) (total * 100 / lenghtOfFile), false);
notification.contentView.setTextViewText(R.id.status_text, Long.toString(total * 100 / lenghtOfFile));
notificationManager.notify(42, notification);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.getCause();
e.getMessage();
}
} catch (Exception e) {
}
}
Is it possible that this code is the reason of the slow dl speeds? Any ideas on how to make the download speed faster?
change this
byte data[] = new byte[1024];
to
byte data[] = new byte[4096];
and as commonsware said,
update your download progress notification in less frequencies.
for eg:
use a simple counter variable in your loop, and update progress when it reaches 10, and then resetting it..!
Maybe you would be better served using DownloadManager.
Android will download the file for you.
if DownloadProvider does not suit you, You could atleast benchmark your code.
You are performing IPC every 1KB of download, as you update your Notification. For a 40MB file, this means you are performing approximately 40,000 IPC calls. Please update your Notification much less frequently.
I suspect that the core problem is the network bandwidth / data rate that your (Android phone's) ISP is providing is much less than your PC gets via its LAN / broadband connection. It could be that your phone is getting a weak signal from the local cell, or that the cell is overloaded, or the backbone is overloaded, or that your ISP has poor peering arrangements.
If that is the problem, there's not much you can do about it except (maybe) change phone carriers or reconfigure your (home?) networking so that your phone can use WiFi to talk to your local WiFi router.

Android copying large inputstream to file very slow

I have an app that is downloading a zip file and then copying this file to a temporary file on the sd card on the phone, but it is being very very slow.
InputStream in = new BufferedInputStream(url.openStream(), 1024);
File tempFile = File.createTempFile("arc", ".zip", targetDir); //target dir is a file
String tempFilePath = tempFile.getAbsolutePath();
OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
//copying file (in different void)
byte[] buffer = new byte[8192];
int len;
len = in.read(buffer);
enter code here
//it loops here for AGES
while (len >= 0) {
out.write(buffer, 0, len);
len = in.read(buffer);
}
in.close();
out.close();
My file is about 20MB, initially I had the buffer size of 1024, and changed it to 8192 thinking it may speed it up but it seemed to make no difference? I always finishes, and I get no errors it just takes ages!
I have searched to try and find a solution but I'm not coming up with anything so I may be going about this totally the wrong way?
Can anyone see what I'm doing wrong?
Bex
Donot increase buffer size. That may cause your application MemoryOutOfBoundsException.
There are varous factors for which your download will be slow. Weak internet connection, Weak file transfer and receiveing mode is also responsible. It also depend on capacity of device. Check whether you are using following code to create inputstream
URL u = new URL("enter url url here");
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
InputStream in = c.getInputStream();
Thanks
Deepak

Categories

Resources