Is there any way in android API 7+ that I can report on the progress of a call to HttpEntity.getContent()?
In my case I am getting an image in the response stream so the transfer can take quite a while. I want to have a ProgressDialog with the style set to STYLE_HORIZONTAL be updated with the progress of the transfer.
Any way to do this?
Thanks!
Have you tried HttpEntity.getContentLength() to help you predetermine the size of the file? If you use that in conjunction with something like AsyncTask's onProgressUpdate(), you should be able to implement that.
Take a look at this link
Download a file with Android, and showing the progress in a ProgressDialog
It has pretty much what you're looking for. it uses urlConnection to get the InputStream so you would need to adapt that to use HttpEntity. So maybe you'd have something like this.
#Override
protected String doInBackground(String... aurl) {
int count;
long contentLength = <yourHttpEntity>.getContentLength();
InputStream input = new BufferedInputStream(<yourHttpEntity>.getContent());
OutputStream output = new FileOutputStream("/sdcard/your_photo.jpg");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/contentLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
and update your dialog in onProgressUpdate.
Related
In my android application I am downloading large files from server(1GB) using the following:
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(7000);
connection.connect();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/Android/" + fileName, true);
byte data[] = new byte[1024];
int count;
int total = 0;
while (count = input.read(data)) > 0) {
total = total + count;
output.write(data, 0, count);
}
The code works well. But sometimes the downloaded file gets corrupted and I don't know why! Is there a mechanism or algorithm, library ... to guarantee a successful download 100%? Please help, I don't know what to do! I don't want to use checksum to check if the file is ok and if not then download it again! I want a solution to detect the problem while downloading and fix the corrupted portion instantly!
In my app, i'm sending a file from a client, using sockets. On the other side, another client receive the file using InputStream and then bufferedOutputStream save the file in the system.
I don´t know why, the file isn´t utterly transmited. I think this is because of network overload, anyway, i don´t know how to solve it.
Transmiter is:
Log.d(TAG,"Reading...");
bufferedInputStream.read(byteArrayFile, 0, byteArrayFile.length);
Log.d(TAG, "Sending...");
bufferedOutputStream.write(byteArrayFile,0,byteArrayFile.length);
bufferedOutputStream.flush();
Receiver is:
bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(file));
byteArray=new byte[fileSize];
int currentOffset = 0;
bytesReaded = bufferedInputStream.read(byteArray,0,byteArray.length);
currentOffset=bytesReaded;
do {
bytesReaded = bufferedInputStream.read(byteArray, currentOffset, (byteArray.length-currentOffset));
if(bytesReaded >= 0){ currentOffset += bytesLeidos;
}
} while(bytesReaded > -1 && currentOffset!=fileSize);
bufferedOutputStream.write(byteArray,0,currentOffset);
You don't state where filesize came from, but there are numerous problems with this code. Too many to mention. Throw it all away and use DataInputStream.readFully(). Or use the following copy loop, which doesn't require a buffer the size of the file, a technique which does not scale, assumes that the file size fits into an int, and adds latency:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Use this at both ends. If you're sending multiple files via the same connection it gets more complex, but you haven't stated that.
I am using the below code to download zip file in android.code works fine ,but sometimes download fails and throws socket exception. especially while Internet connection is slow(i guess).i have also posted the screen shots of logcat error message.
int count;
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
//Log.e("ANDRO_ASYNC", "Lenght of file: " + "="+lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(StorezipFileLocation);
byte data[] = new byte[lenghtOfFile];
long total = 0;
while ((count = input.read(data)) != -1) {
total += c![enter image description here][1]ount;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
connection reset by peer usually means that you are talking to a peer wich think that the connection has already been closed. What I don't understand is why it happens when closing a FileOutputStream.
Besides, the exception does not happen in your code but in the finalizer. Is it possible that when something goes wrong, you catch the exception in an upper level and leave the connection and file opened ? The abandonned connection is closed by the finalyser, but it's too late.
I am not sure that it will solves the problem but it is a good practice to use a finally clause to be sure that files and connections are properly closed.
The log doesn't say where the crash occurs in your code. Isn't there some more info that doesn't appear in your screenshot?
It seems that it fails on the close method of your file input stream.
You could simply surround the calls to close() with a try catch block and set your stream to null (if it failed on closing)
I'a using a asynctask to download file. It works normally until i turn off wifi connection (there are no other internet connection) of my android, download dialog still and no changes. When i check by log, i discover that function read() of inputstream is non stop. So how to check this case? here is my code:
URL url = new URL(this.url);
URLConnection connection = url.openConnection();
connection.setReadTimeout(1000);
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
fileName = "temp.zip";
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
OutputStream output = new FileOutputStream(path+fileName);
byte buffer[] = new byte[1024000];
long total = 0;
int count;
Log.v("test download:","download in background");
while (((count = input.read(buffer)) != -1)) {
Log.v("test download:","read:"+count);
total += count;
publishProgress((int) (total * 100 / fileLength - 1));
output.write(buffer, 0, count);
}
Since you already set a timeout by calling setReadTimeout(), you should get a SocketTimeoutException shortly after the connection dropped.
Do your code happen to maybe capture this exception silently?
Your file download buffer size is too much byte buffer[] = new byte[1024]; is enough
when i try this Download a file with Android, and showing the progress in a ProgressDialog (top answer) with asynctask ,work fine, didn't get that problem
Is there a more efficent way of doing this in terms of memory usage
and performance. The following method downloads a bitmap and calls
a function with the progress.
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
URLConnection connection = url.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream());
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if(imageInterface != null) {
imageInterface.duringDownload(
imageView, ((int)total * 100 / fileLength));
}
outputStream.write(data, 0, count);
}
byte[] byteArray = outputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
input.close();
outputStream.flush();
outputStream.close();
return bitmap;
Your time consuming tasks should not run on UI thread. Use an AsyncTask and update the UI from on onProgressUpdate method.
Increase your bucket size. At the moment you read 1024 byte chunks at a time and update UI after each read. For example for a 1MB image you refresh your UI 1024 times. This is inefficient, so if you increase buffer size you need to do less UI refreshes:
byte data[] = new byte[100 * 1024];
Also, I believe your method is error prone to OutOfMemoryException if it will try to load a large image. To fix this you'll need to scale down the bitmap before assigning it in memory.
Read this article if you are really concerned about efficiency: http://developer.android.com/training/displaying-bitmaps/index.html
Do something similar to the example given in the AsyncTask documentation:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Do not update UI here, only do downloading in background.
protected Long doInBackground(URL... urls) {
while (...) {
// do input.read() and outputStream.write() just like in your original code
// Use AsyncTask method to publish progress
publishProgress((int)total * 100 / fileLength);
}
}
// Here is where you use the progress value to update UI.
protected void onProgressUpdate(Integer... progress) {
imageInterface.duringDownload(
imageView, progress[0]);
}
}