I am using glide to extract a bitmap from the cache and save it elsewhere. The relevant function below (based on this post:) fails to trigger the extraction. In fact, the log line 'Log.d(TAG, "About to start extraction");' below never gets triggered.
Any ideas on why the simple target function never gets called?
public byte[] extractImageFromCache(Context context, String pictureURL) {
byte[] byteArray = new byte[0];
if (context != null && pictureURL != null && !pictureURL.isEmpty()) {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Glide.with(context)
.load(pictureURL)
.asBitmap()
.toBytes()
.diskCacheStrategy(DiskCacheStrategy.SOURCE) // Load the original hires image
.into(new SimpleTarget<byte[]>() {
#Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) {
Log.d(TAG, "About to start extraction");
new AsyncTask<Void, Void, Void>() {
#Override protected Void doInBackground(Void... params) {
Log.d(TAG, "Start extraction");
try {
Log.d(TAG, "Image bytes len: " + resource.length);
byteArrayOutputStream.write(resource);
byteArrayOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
Log.i(TAG, "Unable to load image: " + pictureURL);
e.printStackTrace();
}
return null;
}
}.execute();
}
});
Log.d(TAG, String.format("Got image bytes: %d for %s", byteArrayOutputStream.size(), pictureURL));
return byteArrayOutputStream.toByteArray();
}
return null;
}
As you have mentioned, Log.d(TAG, "About to start extraction") never gets triggered, which means onResourceReady never gets called. This could happen due to some error. Try overriding error callbacks.
To identify the problem I would recommend you to override other callbacks of SimpleTarget to debug the problem.
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
// load has been cleared
}
#Override
public void onLoadStarted(#Nullable Drawable placeholder) {
// load has started
}
#Override
public void onLoadFailed(#Nullable Drawable errorDrawable) {
// load failed due to some reason, notify callers here about the same
}
By using SimpleTarget object we can easily get Bitmap we are trying to extract from cache or network since by default glide look for cache hit.
Modify your Glide loading code to this :
Glide.with(this)
.load("https://cdn-images-1.medium.com/max/1200/1*hcfIq_37pabmAOnw3rhvGA.png")
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
Log.d("Size ", "width :"+resource.getWidth() + " height :"+resource.getHeight());
imageView.setImageBitmap(resource);
storeImage(resource);
}
});
And Using this or any other mechanism for storing bitmap to external/internal storage.
private void storeImage(Bitmap image) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: ");// e.getMessage());
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
image.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
Log.d(TAG, "img dir: " + pictureFile);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
private File getOutputMediaFile(){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ getApplicationContext().getPackageName()
+ "/Files");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
File mediaFile;
Random generator = new Random();
int n = 1000;
n = generator.nextInt(n);
String mImageName = "Image-"+ n +".jpg";
mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
return mediaFile;
}
I am using Glide ver 3.7
compile "com.github.bumptech.glide:glide:3.7.0"
Here is full working example : https://github.com/nieldeokar/GlideApp
First of all, your return is invalid because Glide executes the request in an asynchronous thread. So byteArrayOutputStream is never populated in time before the function returns. This means your function will always return an empty byte array. This also means your log statement Log.d(TAG, String.format("Got image bytes: %d for %s", byteArrayOutputStream.size(), pictureURL)); will be invalid. Knowing this, your About to start extraction will show up after Got image bytes.... You will need to reformat your code to use callbacks to notify the caller of the function that your code has retrieved the array. Something like this:
public interface GlideByteLoadCallback {
void onBytesExtracted(byte[] bytes);
void onFail(String message);
}
public void extractImageFromCache(Context context, String pictureURL, GlideByteLoadCallback callback) {
if (context != null && pictureURL != null && !pictureURL.isEmpty()) {
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Glide.with(context)
.load(pictureURL)
.asBitmap()
.toBytes()
.diskCacheStrategy(DiskCacheStrategy.SOURCE) // Load the original hires image
.into(new SimpleTarget<byte[]>() {
#Override public void onResourceReady(final byte[] resource, GlideAnimation<? super byte[]> glideAnimation) {
Log.d(TAG, "About to start extraction");
new AsyncTask<Void, Void, Void>() {
#Override protected Void doInBackground(Void... params) {
Log.d(TAG, "Start extraction");
try {
Log.d(TAG, "Image bytes len: " + resource.length);
byteArrayOutputStream.write(resource);
byteArrayOutputStream.flush();
if (callback != null) callback.onBytesExtracted(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
e.printStackTrace();
Log.i(TAG, "Unable to load image: " + pictureURL);
e.printStackTrace();
if (callback != null) callback.onFail("Extraction failed");
}
}
}.execute();
}
});
}
if (callback != null) callback.onFail("Invalid url");
}
Then call it with:
extractImageFromCache(context, picture, new GlideByteLoadCallback() {
#Override
public void onFail(String message) {
// handle failure here
}
#Override
public void onBytesExtracted(byte[] bytes) {
// do stuff with bytes here
}
});
This is what I would do.
As you are using glide, place your loaded image to an Image view.
From code, set:
imageView = (ImageView) view.findViewById(R.id.image_view);
imageViewProfile.setDrawingCacheEnabled(true);
imageViewProfile.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
then to get the bitmap from that image view you can use
imageView.getDrawingCache() //This returns a Bitmap
The only thing you should worry about is to verify if Glide finished loading your image or not -I am not sure how to accomplish this-, but give a try and give a vote if this works for you.
Related
I want to resize the gif file and save it. I tried to use some suggested methods but those give error and later I came to know that some of methods are deprecated in Glide v4
byte[] bytes = Glide.with(context)
.asGif()
.load(url)
.toBytes()
.into(250, 250)
.submit()
.get();
In above code converting the arrays to file gives blank gif file with 4.x MB size
File file = Glide.with(reactContext)
.asFile()
.load(url)
.override(512, 512)
.fitCenter()
.into(512,512)
.get();
And
File file = Glide.with(reactContext)
.asFile()
.load(url)
.apply(new RequestOptions().override(512, 512))
// .diskCacheStrategy(DiskCacheStrategy.ALL)
.submit(512,512)
.get();
And
File file = Glide.with(reactContext)
.asFile()
.load(url)
// .override(512, 512)
.fitCenter()
.submit(512,512)
.get();
But the above code keeps the width and height as it is
Details:
Glide version : 4.13.0
Please share the proper code or suggest something to resize the gif (to save as file rather displaying).
Glide can not only load files, but also download them. And that is what you want. You can just use this code and it will be downloaded.
Glide.with(MainActivity.this).asFile()
.load(url)
.apply(new RequestOptions()
.format(DecodeFormat.PREFER_ARGB_8888)
.override(Target.SIZE_ORIGINAL)) // you can also give your size here
.into(new Target<File>() {
#Override
public void onStart() {
}
#Override
public void onStop() {
}
#Override
public void onDestroy() {
}
#Override
public void onLoadStarted(#Nullable Drawable placeholder) {
}
#Override
public void onLoadFailed(#Nullable Drawable errorDrawable) {
}
#Override
public void onResourceReady(#NonNull File resource, #Nullable Transition<? super File> transition) {
storeImage(resource);
}
#Override
public void onLoadCleared(#Nullable Drawable placeholder) {
}
#Override
public void getSize(#NonNull SizeReadyCallback cb) {
}
#Override
public void removeCallback(#NonNull SizeReadyCallback cb) {
}
#Override
public void setRequest(#Nullable Request request) {
}
#Nullable
#Override
public Request getRequest() {
return null;
}
});
The storeImage method:
private void storeImage(File image) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream output = new FileOutputStream(pictureFile);
FileInputStream input = new FileInputStream(image);
FileChannel inputChannel = input.getChannel();
FileChannel outputChannel = output.getChannel();
inputChannel.transferTo(0, inputChannel.size(), outputChannel);
output.close();
input.close();
Toast.makeText(MainActivity.this, "Image Downloaded", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/Diwali Images"); // change the folder name according to your needs.
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs())
return null;
}
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_SHUBH_DIWALI_"+Calendar.getInstance().getTimeInMillis() +".gif"); // change the name of the file according to your wish
return mediaFile;
}
Edit
I have actually found out 1 library for that. In that library, I found this class interesting. Here, in the constructor we can pass the width and height and then we can save it.
In my application, I am able to properly convert the drawable to an image and save it locally on the device. However, I'll need to push the image to Firebase and not save it locally. Here's what I have done.
public void saveImage () {
int count = 0;
File sdDirectory = Environment.getExternalStorageDirectory();
File subDirectory = new File(sdDirectory.toString() + "/Pictures/Paint");
if (subDirectory.exists()) {
File[] existing = subDirectory.listFiles();
for (File file : existing) {
if (file.getName().endsWith(".jpg") || file.getName().endsWith(".png")) {
count++;
}
}
} else {
subDirectory.mkdir();
}
if (subDirectory.exists()) {
File image = new File(subDirectory, "/drawing_" + (count + 1) + ".png");
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(image);
//The code below still doesn't save the image online in firebase.
Uri file = Uri.fromFile(image);
// StorageReference fileRef = reference.child(System.currentTimeMillis() + "." + getFileExtension(file));
StorageReference fileRef = reference.child(System.currentTimeMillis() + ".png");
fileRef.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
fileRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Model model = new Model(uri.toString());
String modelId = root.push().getKey();
root.child(modelId).setValue(model);
progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(getContext(), "Uploaded Successfully!", Toast.LENGTH_SHORT).show();
}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getContext(), "Uploading Failed!", Toast.LENGTH_SHORT).show();
}
});
Boolean bool = mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
Toast.makeText(getContext(), "saved locally", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}
}
It's always failing to upload the file but it successfully saves it locally. I've even just tried to display a notification upon a successful upload but it doesn't even get to the addOnSuccessListener talk less of the onSuccessMethod. I feel like I'm close but what could I be doing wrong?
Your code is ignoring all kinds of error, which make it really hard for you (let alone us) to troubleshoot.
First off: stop catching errors and doing nothing with them, like in } catch (FileNotFoundException e) {. At the very least you should log them with:
Log.e("Storage", "Error uploading image", e)
Same for the IOException, and for public void onFailure(#NonNull Exception e) {: if you log e there too, you may be able to find (in your logcat output) what is going wrong.
I have chat screen where i am downloading attachment from FirebaeStorage.
I have various formats of file which can be send doc,pdf,apk etc. and for each i have same TextViews and ImageViews.
In Chat screen's recyclerview adapter i am setting file path of local storage which can be obtain by run AsyncTask which downloads files from Firebase Storage and return file path.This work perfectly but the issue is how to get back that file path in onBindViewHolder on particular if else
Here is my RecyclerAdapter where i am calling AsyncTask and need result back into same scope and wait till download completes then set views according to data returned
public void onBindViewHolder(final Chat_Adapter.ViewHolder holder, int position) {
if (fileType.equals("pdf")){
new DownloadFileFromFS(Download_URL,FileName+".pdf").execute();
//HERE I NEED THE RESULT FROM ASYNCTASK AND WAIT TILL DOWNLOAD COMPLETES
//THEN SET THE VIEWS WITH RETURN RESULT FROM ASYNCTASK
if (DownloadFilePath!=null){
File file=new File(DownloadFilePath);
long sizeFile=file.length()/1024; //In KB
holder.Doc_FileName.setText(DownloadFilePath);
holder.Doc_FileSize.setText(String.valueOf(sizeFile));
}
else {
Log.d(TAG,"DOWNLOAD FILE PATH IS NULL");
}
}
AsyncTask
public class DownloadAttachment extends AsyncTask<Void, String, String> {
String DownloadUrl,fileName;
File file;
Context context;
ProgressBar progressBar;
public static final String TAG="###Download Attachment";
public DownloadAttachment(Context context, String downloadUrl, String fileName) {
DownloadUrl = downloadUrl;
this.fileName = fileName;
this.context=context;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
#Override
protected String doInBackground(Void... params) {
int count;
try {
File root = android.os.Environment.getExternalStorageDirectory();
Log.d(TAG,"DO IN BACKGROUND RUNNING");
File dir = new File(root.getAbsolutePath() + "/Downloaded Files/");
if (dir.exists() == false) {
dir.mkdirs();
}
URL url = new URL(DownloadUrl); //you can write here any link
file = new File(dir, fileName);
long startTime = System.currentTimeMillis();
Log.d(TAG, "download begining");
Log.d(TAG, "download url:" + url);
Log.d(TAG, "downloaded file name:" + fileName);
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
//this will be useful so that you can show a typical 0-100% progress bar
int lengthOfFile=ucon.getContentLength();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayOutputStream baf = new ByteArrayOutputStream(5000);
int current = 0;
long total=0;
while ((current = bis.read()) != -1) {
baf.write((byte) current);
total=total+current;
//PUBLISH THE PROGRESS
//AFTER THIS onProgressUpdate will be called
publishProgress(""+(int)(total*100)/lengthOfFile);
}
/* Convert the Bytes read to a String. */
FileOutputStream fos = new FileOutputStream(file);
fos.write(baf.toByteArray());
fos.flush();
fos.close();
Log.d("DownloadManager", "download ready in " + ((System.currentTimeMillis() - startTime) / 1000) + " sec");
Log.d(TAG,"File Path "+file);
} catch (IOException e) {
Log.d("DownloadManager", "Error: " + e);
}
return file.toString();
}
}
UPDATE As #Atef Hares suggest,i did implement in code.its working fine but what if i have different format. How to call particular if else after getting result from asynctask cuz code suggested only call pdf if statement.
if (fileType.equals("pdf")){
final String nameFile=UUID.randomUUID().toString();
new DownloadFileFromFS(chat_wrapper.getDocuments(),nameFile).execute();
filePathInterface=new FilePath() {
#Override
public void LocalFilePath(final String Path) {
//HERE I AM GETTING RESULT FROM ASYNCTASK
//AND SETTING VIEWS ACCORDING TO IT
}
};
}
else if (fileType.equals("doc")){
//HOW TO GET RESULT FROM ASYNCTASK HERE IF FILETYPE IS "doc"
}
else if (fileType.equals("ppt")){
//HOW TO GET RESULT FROM ASYNCTASK HERE IF FILETYPE IS "ppt"
}
Okay using interfaces -as you know- will achieve what you need!
just do it like this:
public interface AsyncTaskCallback {
void onSuccess (String filePath);
}
and in the Adapter, don't set any data to the view unless you got the data back from asyncTask, like this:
public void onBindViewHolder(final Chat_Adapter.ViewHolder holder, int position) {
//Initialize filetype here
new DownloadFileFromFS(Download_URL, FileName + "."+ filetype, new AsyncTaskCallback() {
#Override
public void onSuccess(String filePath) {
//HERE I NEED THE RESULT FROM ASYNCTASK AND WAIT TILL DOWNLOAD COMPLETES
//THEN SET THE VIEWS WITH RETURN RESULT FROM ASYNCTASK
if (filePath != null) {
File file = new File(filePath);
long sizeFile = file.length() / 1024; //In KB
holder.Doc_FileName.setText(filePath);
holder.Doc_FileSize.setText(String.valueOf(sizeFile));
} else {
Log.d(TAG, "DOWNLOAD FILE PATH IS NULL");
}
}
}).execute();
}
You could use a callback.
public interface FileDownloadCallback {
void onSuccess (String filePath);
void onFailed ();
}
Pass that in to your AsyncTask and call it from onPostExecute.
Im Still fresh so go easy.
This is my OnClickListener for my camera
buttonClick = (Button) findViewById(R.id.btnCapture);
buttonClick.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
preview.mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
}
);}
And this is the code to save to sd card
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
#Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
// Write to SD Card
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File(sdCard.getAbsolutePath() + "/camtest");
dir.mkdirs();
String fileName = String.format("%d.jpg", System.currentTimeMillis());
File outFile = new File(dir, fileName);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to " + outFile.getAbsolutePath());
refreshGallery(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
and then i call my sliding layer up
public void buttonClicked(View v){
switch (v.getId()) {
case R.id.btnCapture:
if (!mSlidingLayer.isOpened()) {
mSlidingLayer.openLayer(true);
}
break;
case R.id.buttonClose:
if (mSlidingLayer.isOpened()) {
mSlidingLayer.closeLayer(true);
}
break;
}
}
How do i implement my OnClickListener from my camera with the buttonClicked from my sliding layer in one instance.
I tried combining the two but that gave me the RuntimeException: Canvas: trying to use a recycled bitmap error because the sliding layer was coming into effect before the Save Image Task could complete.
Any help would be great.
Kind regards Sean.
Trigger the code to slide your layer in the onPostExecute() method of your AsyncTask. This method will be called when the task has completed, and will be called on the main thread so you can safely manipulate UI classes.
I want my program to download many images (around 500) from the internet and store them in my external storage. Currently when I download a single image, it shows a progressBar and downloads the image properly. However when I am trying to replicate w/ two images, it gives the Toast for "Download complete" for both images being downloaded, however no progressBar for either image is shown and only the first image is properly downloaded.
Here is the code for my onCreate method for activity.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove Title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//force portrait orientation. (No landscape orientation).
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_quran);
//Instantiate ProgressDialog (Used for downloading quran pages).
myProgressDialog = new ProgressDialog(QuranActivity.this);
myProgressDialog.setMessage("Downloading Quran");
myProgressDialog.setIndeterminate(true);
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myProgressDialog.setCancelable(true);
//execute when the downloader must be fired.
final DownloadTask downloadTask = new DownloadTask(QuranActivity.this);
DownloadTask second = new DownloadTask(getApplicationContext());
myHTTPURL = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0001.jp2&scale=1&rotate=0";
myHTTPURL2 = "https://ia601608.us.archive.org/BookReader/BookReaderImages.php?zip=/10/items/05Quran15LineWhitePageWithVioletBorderWww.Momeen.blogspot.com/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2.zip&file=05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_jp2/05%20Quran%2015%20Line%20[White%20page%20with%20Violet%20border]%20-%20www.Momeen.blogspot.com_0002.jp2&scale=1&rotate=0";
//First check if the file has already been created. (Only need to download 1ce, or
//in the case where the user deleted the files, we reinstall them again).
if (isExternalStorageWritable()) {
File makeDirectory = getQuranStorageDir(QuranActivity.this, "Quran_Pages");
for (int i = 0; i < 2; i++) {
Bundle myBundle = new Bundle();
myBundle.putInt("i", i);
if (i == 0) {
downloadTask.execute(myHTTPURL);
try {
downloadTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
myProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
} else {
/*if (downloadTask.getStatus() == AsyncTask.Status.FINISHED) {
downloadTask.execute(myHTTPURL2);
} else if (downloadTask.getStatus() == AsyncTask.Status.RUNNING) {
try {
downloadTask.execute(myHTTPURL2).wait(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} */
second.execute(myHTTPURL2);
try {
second.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// downloadTask.execute(myHTTPURL2);
}
}
}
and this is the code for my AsynTask Class.
#TargetApi(Build.VERSION_CODES.FROYO)
private class DownloadTask extends AsyncTask {
private Context context;
private PowerManager.WakeLock myWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
//Display download percentage.
int fileLength = connection.getContentLength();
//create folder to place the downloaded file in.
// File Path:E:\Android\data\com.syedabdullah.syed.quran_memorization_application
// \files\Quran Memorization Application\Quran_Pictures
//So first create a root folder Quran Memorization Application then inside that
//folder we create another folder named Quran Pictures.
/* File rootFolder = new File(getExternalFilesDir("Quran Memorization Application"),
"Quran_Pages"); */
//Here we insert inside the Quran_Pictures folder the quran_pages.
//String myFileName = "quran_01.jpg";
Bundle y = new Bundle();
int retrievePos = y.getInt("i");
String quranFilePageName = "_" + retrievePos + ".jpg";
// String fileName = "justwork.jpg";
File sup = new File(getExternalFilesDir("Quran Memorization Application"), "Quran_Pages");
File myFile = new File(sup, quranFilePageName);
myFile.createNewFile();
//downlaod the file.
input = connection.getInputStream();
output = new FileOutputStream(myFile);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
//allow cancel with back button.
if (isCancelled()) {
input.close();
return null;
}
total += count;
//publish the progress.
if (fileLength > 0) {
publishProgress((int) (total * 100 / fileLength));
}
output.write(data, 0, count);
}
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(myFile));
QuranActivity.this.sendBroadcast(intent);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (connection != null) {
connection.disconnect();
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//Take CPU lock to prevent CPU from going off if the user presses the power button.
//during download.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
myWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
myWakeLock.acquire();
myProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
//If we get here length is known, so setIndertimante to false.
myProgressDialog.setIndeterminate(false);
myProgressDialog.setMax(100);
myProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
myWakeLock.release();
myProgressDialog.dismiss();
if (result != null) {
Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Download Complete", Toast.LENGTH_SHORT).show();
}
}
} }
I was hoping to have a for loop that would create hundreds of downloadTasks and download all the images I need, and then I would call the get method. However in order for that to work, I first need too know why when I try for 2 images only the first one gets downloaded and why no progressbar shows up. Also if possible if I could get a hint as to how I can make my progressBar update for all the images and not be designed for just 1. Thanks in advance. (Note all URLs are currect.)
Thank you so much! figured out that my loops were suppose to go inside doInBackground. Also to anyone else having a similar issue. To download multiple files and display a decent progressBar, here is a very great tutorial: http://theopentutorials.com/tutorials/android/dialog/android-download-multiple-files-showing-progress-bar/