i have a following code to download an image , show a progress bar and return its bitmap. but the bitmap always returns null.. once i remove the while loop, the bitmap has value, but i dont get a progress bar.
#Override
protected Bitmap doInBackground(String... params) {
bitmap = null;
try {
URL url = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
int lenghtOfFile = connection.getContentLength();
InputStream input = connection.getInputStream();
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/DCIM/downloadedfile.jpg");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
Bitmap bitmap = BitmapFactory.decodeStream(input);
return bitmap;
} catch (IOException e) {
Log.e("could not load ", e.getMessage());
e.printStackTrace();
return null;
}
}
protected void onProgressUpdate(Integer... progress) {
pDialog.setProgress(progress[0]);
}
public void onPostExecute(Bitmap result) {
pDialog.dismiss();
listener.onTaskCompleted(result);
}
enter code here
an InputStream can only read one time. you need to change your code to :
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
String pathName=Environment
.getExternalStorageDirectory().toString()
+ "/DCIM/downloadedfile.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(pathName);
you don't need interface because asynctask can return bitmap.
private class DownloadFilesTask extends AsyncTask<String, Integer, Bitmap> {
protected Bitmap doInBackground(String... params) {
return downloadBitmap();
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
}
When you call task you must use get();
Bitmap bitmap = new DownloadFileTask().execute().get();
Related
I am trying to download an Image and then display it to my imageView component.
To download I have to use Asyntask and display a progress bar to inform a user. Problem is after going through a loop to get the calculated progress value I get 0 from inputStream.
Log.d("is", "" + inputStream.available()); // ---> will have a value
byte[] buffer = new byte[contentLenght];
while ((read = inputStream.read(buffer)) != -1) {
counter += read;
publishProgress(counter);
outputStream.write(buffer,0,read);
}
Log.d("is", "" + inputStream.available()); // -----> will return 0
bmp = BitmapFactory.decodeStream(inputStream); // bmp will be empty
Is there a way to get the calcuated value for progress bar and not get a 0 value at the end in input stream?
I am using Asyntask here.
Clarification
bmp will have a value and when I do this
imageView.setImageBitmap(bmp); it will work ONLY IF i remove the the loop and just call bmp = BitmapFactory.decodeStream(inputStream);
However if I put a loop before doing this
bmp = BitmapFactory.decodeStream(inputStream);
the imageView will show nothing
Here is my Full Asynctask Code Including the networking connection
int progressCounter;
int contentLenght;
int counter;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected Boolean doInBackground(String... params) {
return ConnectToInternet(params[0]);
}
#Override
protected void onPostExecute(Boolean aVoid) {
//Log.d("buff",bmp.toString());
progressBar.setVisibility(View.GONE);
imageView.setImageBitmap(bmp);
}
#Override
protected void onProgressUpdate(Integer... values) {
progressCounter =(int) (((double) values[0] / contentLenght) * 100);
progressBar.setProgress(progressCounter);
}
boolean ConnectToInternet(String url){
boolean sucessfull = false;
URL downloadURL = null;
HttpURLConnection connection = null;
InputStream inputStream = null;
try {
downloadURL = new URL(url);
connection = (HttpURLConnection) downloadURL.openConnection();
inputStream = connection.getInputStream();
contentLenght = connection.getContentLength();
Log.d("is", "" + inputStream.available());
int read = -1;
byte[] buffer = new byte[contentLenght];
while ((read = inputStream.read(buffer)) != -1) {
counter += read;
publishProgress(counter);
}
Log.d("is", "" + inputStream.available());
bmp = BitmapFactory.decodeStream(inputStream);
sucessfull = true;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
connection.disconnect();
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sucessfull;
}
thanks
The while statement is consuming the inputStream entirely, so nothing will be left for decoding in BitmapFactory.decodeStream(inputStream).
Try this:
boolean ConnectToInternet(String url){
// ...
int read;
// contentLength may be too big,
// so read stream in smaller chunks.
//
// there's a typo in contentLenght :)
byte[] buffer = new byte[4096];
// Object for storing partially downloaded image.
ByteArrayOutputStream imageBaos = new ByteArrayOutputStream();
// Initialize counter.
counter = 0;
while ((read = inputStream.read(buffer)) != -1) {
counter += read;
publishProgress(counter);
// Store downloaded chunk.
imageBaos.write(buffer, 0, read);
}
// Obtain bitmap from downloaded chunks.
bmp = BitmapFactory.decodeByteArray(imageBaos.toByteArray(), 0, imageBaos.size());
// ...
}
I want to download an image via AsyncTask and want to display it in an ImageView I am able to do it normally but I also want to show the progress to the user and do all this without having to store the file in the SDcard.
Here is what I have done so far.
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread
* Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
OutputStream output = new FileOutputStream("/sdcard/downloadedfile.jpg");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task
* Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
// Displaying downloaded image into image view
// Reading image path from sdcard
String imagePath = Environment.getExternalStorageDirectory().toString() + "/downloadedfile.jpg";
// setting downloaded into image view
my_image.setImageDrawable(Drawable.createFromPath(imagePath));
}
}
If you don't want to download image locally, you should use ByteArrayOutputStream instead of FileOutputStream.
And this is the key code:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lenghtOfFile));
outputStream.write(data, 0, count);
}
//after downloading the image
byte[] imageData = outputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
my_image.setImageBitmap(bitmap);
I didn't test it, but I believe this can help you.
You can use Glide instead:
Glide.with(this).load("http://server.com/image.jpg").into(imageView);
reference Best method to download image from url in Android
private Bitmap downloadBitmap(String url) {
HttpURLConnection urlConnection = null;
try {
URL uri = new URL(url);
urlConnection = (HttpURLConnection) uri.openConnection();
int statusCode = urlConnection.getResponseCode();
if (statusCode != HttpStatus.SC_OK) {
return null;
}
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (Exception e) {
Log.d("URLCONNECTIONERROR", e.toString());
if (urlConnection != null) {
urlConnection.disconnect();
}
Log.w("ImageDownloader", "Error downloading image from " + url);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return null;
}
I am trying to download a file from my server in Android and updating the progress..
On Async method in background I am calling a method that will download the file to my SD card now I would like update the progress hence trying publishProgress("" + progressvalue); which I am not able access from this method. How do I access the publishProgress?
Here is what I am trying:
private class FileDownloader extends AsyncTask<String, String, Void> {
#Override
protected Void doInBackground(String... param) {
downloadFileToSdCard(param[0], "File" + counter + ".mp4");
return null;
}
protected void onProgressUpdate(String... values)
{
Log.d("ANDRO_ASYNC", values[0]);
}
}
downloadFileToSdCard method looks like this:
private void downloadImagesToSdCard(String downloadUrl, String fileName)]
{
FileOutputStream fos;
InputStream inputStream = null;
try {
URL url = new URL(downloadUrl);
String sdCard = Environment.getExternalStorageDirectory().toString();
File myDir = new File(sdCard, "AppDownload");
if (!myDir.exists()) {
myDir.mkdir();
}
String fname = fileName;
File file = new File(myDir, fname);
if (file.exists())
file.delete();
URLConnection ucon = url.openConnection();
final String contentLengthStr=ucon.getHeaderField("content-length");
int lenghtOfFile = Integer.valueOf(contentLengthStr);
HttpURLConnection httpConn = (HttpURLConnection) ucon;
httpConn.setRequestMethod("GET");
httpConn.connect();
inputStream = httpConn.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bufferLength = 0;
long total = 0;
int progress = 0;
while ((bufferLength = inputStream.read(buffer)) > 0)
{
total += bufferLength;
int progress_temp = (int) total * 100 / lenghtOfFile;
publishProgress("" + progress_temp);
if (progress_temp % 10 == 0 && progress != progress_temp)
{
progress = progress_temp;
}
fos.write(buffer, 0, bufferLength);
int downloadedSize = Integer.valueOf(contentLengthStr);
}
inputStream.close();
fos.close();
Log.e("Value", "File Saved in sdcard..");
} catch (IOException io) {
inputStream = null;
fos = null;
io.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
Can somebody help me fix this? Thanks!
Triy this:
keep you function inside into AsyncTask Class
private class FileDownloader extends AsyncTask<String, String, Void> {
#Override
protected Void doInBackground(String... param) {
downloadFileToSdCard(param[0], "File" + counter + ".mp4");
return null;
}
protected void onProgressUpdate(String... values)
{
Log.d("ANDRO_ASYNC", values[0]);
}
private void downloadImagesToSdCard(String downloadUrl, String fileName)
{
//Publish Progress calling code
}
}
The first thing that hits me is to simply pass your AsyncTask to your sdcard method. AsyncTask.publishProgress is protected, so as long as your two classes are in the same package, you should be able to call publishProgress from the sdcard downloaded method.
A cleaner/prettier approach would be to define a callback interface such as ProgressUpdater, let the AsyncTask implement it, and have the sdcard method take a ProgressUpdater as a parameter. This interface would typically have a similar or even equal publishProgress method. This however decouples the AsyncTask itself from the rest of your program.
I have one problem in url like"http://sample.com/test" that have large amout of xml data i am not able to show progress bar in mainUI.
Please do needful.
In AsyncTask ,background task save the xml in local memory.
int count;
try {
URL url = new URL("http://sample.com/test");
URLConnection conection = url.openConnection();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
OutputStream output = new FileOutputStream("/data/data/com.pc.demo/temp.xml");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
int progress = (int)((total*100)/lenghtOfFile) ;
System.out.println("update---"+progress);
publishProgress(progress);
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
onPostExecute
File yourFile = new File("/data/data/com.pc.demo/temp.xml");
InputStream input = new BufferedInputStream(new FileInputStream(yourFile), 8086);
onProgressUpdate
setProgressPercent(progress[0])
you can override the onProgressUpdate() function of your AsyncTask, and use the publishProgress(Progress... values) in the doInBackgroud() to push your saving status to the progress then update it, here is my simple code, wish can help you.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]); //change this with your progress bar
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
I have read this topic
and I have a problem about downloading large files, because progress dialog does not upload progress or upload only once after downloading and show 100% suddenly. But all works perfectly when I'm downloading small files.
I think problem may be here:
publishProgress((int)(total*100/fileLength));
My code:
private class DownloadFile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
URL url = new URL(sUrl[0]);
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
String sdpath = Environment.getExternalStorageDirectory().getAbsolutePat();
File dir = new File(sdpath + "/Myfolder");
dir.mkdir();
OutputStream output = new FileOutputStream(dir.toString() + "/" + "myfilename");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int)(total/fileLength)*100);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
mProgressDialog.setProgress(progress[0]);
}
}
My file is about 80 mb.
You should try to divide first :
publishProgress((int)(total/fileLength)*100);
as you can get an out of range division.