My situation is a RecyclerView of invoices that can be downloaded. They have an action that starts the download and shows the progress in a circular progress view around the download button itself. I use an AsyncTask to download the particular invoice in PDF format, with a custom listener so I know when is cancelled, executed and progress updated outside the AsyncTask itself (to avoid passing the View and updating it inside the AsyncTask mostly).
This is my AsyncTask so far:
public class DownloadTask extends AsyncTask<URL, Integer, String> implements Codes {
private AsyncTaskProgressListener listener;
private File file;
public DownloadTask(AsyncTaskProgressListener listener) {
this.listener = listener;
}
#Override
protected String doInBackground(URL... urls) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = urls[0];
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + url.getFile());
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
int fileLength = connection.getContentLength();
LogUtil.log("" + fileLength);
// download the file
input = connection.getInputStream();
output = new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), url.getFile()));
byte data[] = new byte[4096];
long total = 0;
int count;
int lastProgress = 0;
while ((count = input.read(data)) != -1) {
if (isCancelled()) {
break;
}
total += count;
// publishing the progress....
int progress = 0;
if (fileLength > 0) {
// only if total length is known
progress = (int) (total * 100 / fileLength);
}
//Prevent publishing the same progress various times as it would freeze the progress bar.
if (progress > lastProgress) {
publishProgress(progress);
lastProgress = progress;
}
output.write(data, 0, count);
}
} catch (Exception e) {
LogUtil.log(e.toString());
return e.toString();
} 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 onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
listener.onProgressUpdated(values[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
listener.onCompleted();
}
#Override
protected void onCancelled(String s) {
listener.onCancel();
file.delete();
LogUtil.log("CANCELED");
super.onCancelled(s);
//noinspection ResultOfMethodCallIgnored
}
}
And my listener:
tasks[0] = new DownloadTask(new AsyncTaskProgressListener() {
#Override
public void onCompleted() {
state = INVOICE_DOWNLOADED;
}
#Override
public void onCancel() {
state = INVOICE_NOT_DOWNLOADED;
progressView.resetAnimation();
}
#Override
public void onProgressUpdated(int progress) {
progressView.setProgress(progress);
}
});
This is what's called when I press the cancel button:
progressView.setProgress(0);
if (tasks[0] != null)
tasks[0].cancel(true);
And finally my problem:
I found that when I cancel the download, mostly when it's after 50%, there is one last call to onProgressUpdated(progress) AFTER the progressView.setProgress(0) so the download is cancelled but the progress bar is stuck at the last progress instead of going to 0 (When you set a new progress, it animates itself in a very cool way).
I tried to workaround this in various ways, like having a boolean on the AsyncTask to know if it's canceled, a method that sets it to true, and a check of it in onProgressUpdated(progress) of the AsyncTask before calling the onProgressUpdated(progress) of the listener which sets the progress on the view; and I didn't be able to find a solution.
the onProgressUpdated() and progressView.setProgress(0); both run on UI thread, so you can add a boolean check with them.
add a boolean field boolean noMoreProgressUpdate = false
add noMoreProgressUpdate = true after progressView.setProgress(0);
change
public void onProgressUpdated(int progress) {
progressView.setProgress(progress);
}
to
`
public void onProgressUpdated(int progress) {
if(!noMoreProgressUpdate) {
progressView.setProgress(progress);
}
}
`
I'd use
onPreExecute() {
//do progress bar here
}
and then in onPostExecute()
onPostExecute(String result) {
//dismiss progress bar before anything else
}
Related
Hi i am trying to download a video from server using API by default android download manager. everything is working fine but not in Android 10. i Want to save that video to my public directory that video should appear in photos and Files (working well <API 29)
code i am using
private class DownloadTask extends AsyncTask<String, Integer, String> {
DownloadTask(Context context) {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
PlayMovieActivity.mProgressDialog.setVisibility(View.VISIBLE);
}
#Override
protected void onProgressUpdate(Integer... progress) {
PlayMovieActivity.mProgressDialog.setIndeterminate(false);
PlayMovieActivity.mProgressDialog.setMax(100);
PlayMovieActivity.mProgressDialog.setProgress(progress[0]);
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
//getPath();
PlayMovieActivity.mProgressDialog.setVisibility(View.GONE);
if (result != null) {
savedownload();
PlayMovieActivity.doneok.setVisibility(View.VISIBLE);
PlayMovieActivity.downprogress.setVisibility(View.GONE);
PlayMovieActivity.downbtn.setVisibility(View.GONE);
PlayMovieActivity.downnow.setVisibility(View.GONE);
}
else {
PlayMovieActivity.downnow.setVisibility(View.GONE);
PlayMovieActivity.downbtn.setVisibility(View.VISIBLE);
PlayMovieActivity.doneok.setVisibility(View.GONE);
PlayMovieActivity.downprogress.setVisibility(View.GONE);
PlayMovieActivity.doneok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openDown();
}
});
}
}
#Override
protected String doInBackground(String... sUrl) {
PlayMovieActivity.input = null;
PlayMovieActivity.connection = null;
try {
URL url = new URL(sUrl[0]);
PlayMovieActivity.connection = (HttpURLConnection) url.openConnection();
PlayMovieActivity.connection.connect();
if (PlayMovieActivity.connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + PlayMovieActivity.connection.getResponseCode()
+ " " + PlayMovieActivity.connection.getResponseMessage();
}
final int fileLength = PlayMovieActivity.connection.getContentLength();
PlayMovieActivity.input = PlayMovieActivity.connection.getInputStream();
callDownloadManager();
int count;
while ((count = PlayMovieActivity.input.read(data)) != -1) {
total += count;
if (fileLength > 0) {
publishProgress((int) (total * 100 / fileLength));
final long finalTotal1 = total;
c.runOnUiThread(new Runnable() {
public void run() {
PlayMovieActivity.tv.setText(String.valueOf((int) (finalTotal1 * 100 / fileLength)));
PlayMovieActivity.downbtn.setVisibility(View.GONE);
PlayMovieActivity.downprogress.setVisibility(View.VISIBLE);
PlayMovieActivity.doneok.setVisibility(View.GONE);
PlayMovieActivity.downnow.setVisibility(View.VISIBLE);
PlayMovieActivity.downnow.setText("Now Downloading : "+StoreClass.downtitle);
}
});
}
}
} catch (Exception e) {
}
return null;
}
}
CALL DOWNLOAD FUNCTION
private void callDownloadManager() {
Uri uri = Uri.parse(downurl);
PlayMovieActivity.downloadManager = (DownloadManager) c.getSystemService(Context.DOWNLOAD_SERVICE);
PlayMovieActivity.request = new DownloadManager.Request(uri);
PlayMovieActivity.request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
PlayMovieActivity.request.setDescription("Downloading");
filename = downurl.substring(downurl.lastIndexOf("/")+1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
PlayMovieActivity.request.setDestinationInExternalFilesDir(c,Environment.getExternalStorageDirectory().getPath()+"Movie",filename);
}
else
{
PlayMovieActivity.request.setDestinationInExternalPublicDir("Movie",filename);
}
PlayMovieActivity.request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
PlayMovieActivity.request.setMimeType(MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(downurl)));
StoreClass.stop_Id = PlayMovieActivity.downloadManager.enqueue(PlayMovieActivity.request);
}
THIS CODE IS WORKING WELL <API29
PlayMovieActivity.request.setDestinationInExternalPublicDir("Movie",filename);
THIS CODE IS WORKING BUT VIDEO SAVED TO
android.data.com.package.files.storage.emulated.Folder
PlayMovieActivity.request.setDestinationInExternalFilesDir(c,Environment.getExternalStorageDirectory().getPath()+"Movie",filename);
MANIFEST
android:requestLegacyExternalStorage="true"
what i want to save or copy/move the whole video to photos gallery or public gallery
I want to cast SlideshowDialogFragment to context in my asynctask in DdownloadTask.java but when i write
final DownloadTask downloadTask = new
DownloadTask(myActivity.this);
SlideshowDialogFragment instead of myActivity , android show warning and say
warning android
i don't know what am i do ?? thx for help me
public class SlideshowDialogFragment extends DialogFragment{
ArrayList<Image> images;
ViewPager viewPager;
MyViewPagerAdapter myViewPagerAdapter;
TextView lblCount,lblTitle,lblDate;
Button btn_set;
Button btn_download;
int selectedPostition;
DownloadManager downloadManager;
public static ProgressDialog mProgressDialog;
static SlideshowDialogFragment newInstance(){
SlideshowDialogFragment f=new SlideshowDialogFragment();
return f;
}
#Override
public View onCreateView (LayoutInflater inflater,ViewGroup container,Bundle saveInstanceState)
{
View v=inflater.inflate(R.layout.fragment_image_slider,container,false);
viewPager=(ViewPager)v.findViewById(R.id.view_pager);
lblTitle=(TextView)v.findViewById(R.id.title);
lblDate=(TextView)v.findViewById(R.id.date);
btn_set=(Button)v.findViewById(R.id.btn_set);
btn_download=(Button)v.findViewById(R.id.btn_download);
images=(ArrayList<Image>) getArguments().getSerializable("images");
selectedPostition=getArguments().getInt("position");
myViewPagerAdapter=new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int
positionOffsetPixels) {
displayInfo(position);
//setWallpaper(position);
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
setCurrentItem(selectedPostition);
btn_download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
download(selectedPostition);
}
});
return v;
}
void download (int position){
Image image=images.get(position);
String large = image.getlarge();
final DownloadTask downloadTask = new
DownloadTask(**SlideshowDialogFragment**.this);
downloadTask.execute(large);
}
And this is DownloadTask Activity with constructor i write AsyncTask in this class:
public class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
private PowerManager.WakeLock mWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#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);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
mWakeLock.acquire();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
mWakeLock.release();
mProgressDialog.dismiss();
if (result != null)
Toast.makeText(context,"خطای دانلود "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"دانلود با موفقیت انجام شد",
Toast.LENGTH_SHORT).show();
}
#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.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/tabriz.jpg");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
}
what am i do for casting SlideshowDialogFragment to Async ?
You need to pass a Context as you defined your constructor like that. A Fragment does not have a Context, but the Activity has it. Since Fragment is a part of an Activity you can access it with
SlideshowDialogFragment.this.getActivity();
You could also use it directly with DownloadTask(getActivity())
I work with a RecyclerView that looks like this.
I use an AsyncTask for managing the downloads. I use this button so that each item in the list of cards can have the progress of the respective download. I am not sure how to report the status of the download to the RecyclerView. How do I get this to post updates to the cards?
The async downloader code is this
public class DownloadFileFromURL extends AsyncTask<String, String, String> {
private final String resourceType;
public DownloadFileFromURL(String resourceType) {
super();
this.resourceType = resourceType;
// do stuff
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//showDialog(progress_bar_type);
}
protected void onProgressUpdate(String... progress) {
// setting progress percentage
// pDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
String fileName = url.toString().substring(url.toString().lastIndexOf('/') + 1);
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lengthOfFile = connection.getContentLength();
Log.d("lengthofFile", String.valueOf(lengthOfFile));
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
String destinationDirectory ="";
if(resourceType.equals(SyncUtil.IMAGE_ZIP)) {
destinationDirectory= SyncUtil.TMP;
}
if(resourceType.equals(SyncUtil.VIDEOFILE)) {
destinationDirectory = SyncUtil.VIDEO;
}
File mFolder = new File(AppController.root.toString() + File.separator+destinationDirectory);
if (!mFolder.exists()) {
mFolder.mkdir();
}
OutputStream output = new FileOutputStream(AppController.root.toString()+File.separator+destinationDirectory+File.separator
+ fileName);
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) / lengthOfFile));
output.write(data, 0, count);
}
output.flush();
// closing streams
output.close();
input.close();
if(resourceType.equals(SyncUtil.IMAGE_ZIP)) {
BusProvider.getInstance().post(new ZipDownloadComplete(fileName,resourceType));
}
if(resourceType.equals(SyncUtil.VIDEOFILE)) {
// BusProvider.getInstance().post(new VideoDownloadComplete(fileName));
}
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(String file_url) {
}
}
The RecyclerView adapter is here
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Video video = videosList.get(position);
holder.title.setText(video.getTitle());
holder.description.setText(video.getDescription());
holder.downloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String url ="http://"+ AppController.serverAddr +":"+AppController.port +"/video/"+video.getUrl()+video.getExtension();
DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL(SyncUtil.VIDEOFILE);
downloadFileFromURL.execute(url,video.getTitle(),video.getDescription());
}
});
holder.bind(video,listener);
}
Though its not a very good solution but in my case I got that working. I'm just sharing my thoughts with some sample code snippet.
I assume you're showing the download progress with a ProgressBar. So take an instance of the ProgressBar in your adapter and pass the reference to your AsyncTask.
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Video video = videosList.get(position);
holder.title.setText(video.getTitle());
holder.description.setText(video.getDescription());
holder.downloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String url ="http://"+ AppController.serverAddr +":"+AppController.port +"/video/"+video.getUrl()+video.getExtension();
// Pass the progressBar here. You might have to set it as a final variable.
DownloadFileFromURL downloadFileFromURL = new DownloadFileFromURL(SyncUtil.VIDEOFILE, holder.progressBar);
downloadFileFromURL.execute(url,video.getTitle(),video.getDescription());
}
});
holder.bind(video,listener);
}
Now modify your constructor of the AsyncTask like this.
public DownloadFileFromURL(... , ProgressBar mProgressbar) {
this.mProgressbar = mProgressbar;
this.mProgressbar.setProgress(0);
this.mProgressbar.setMax(100);
}
Add onProgressUpdate in your AsyncTask
protected void onProgressUpdate(Integer... values) {
mProgressbar.setProgress(values[0]);
}
Now in your doInBackground calculate the file size and publish the progress after a certain amount of file is downloaded.
protected void doInBackground() throws IOException {
try {
// Establish connection
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
final String contentLengthStr = connection.getHeaderField("content-length");
InputStream input = connection.getInputStream();
String data1 = f.getPath();
FileOutputStream stream = new FileOutputStream(data1);
byte data[] = new byte[4096];
int count;
int progressCount = 0;
while ((count = input.read(data)) != -1) {
stream.write(data, 0, count);
progressCount = progressCount + count;
int progress = (int) (((progressCount * 1.0f) / Integer.parseInt(contentLengthStr)) * 10000);
// Publish your progress here
publishProgress(progress);
}
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Note:
Passing the original reference of your views is not a very good solution. I would rather set a BroadcastReceiver in my activity and would publish a broadcast with the specific item position in the publishProgress function. So that when the broadcast is received in the main activity, I could call notifyDatasetChanged to take progress effect in the list.
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/
I am doing a function to download files to android device, works fine but I want to do that if the downloaded file exists already in the device will overwrite it. Here is my code:
class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
private PowerManager.WakeLock mWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#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);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
mWakeLock.acquire();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
mWakeLock.release();
mProgressDialog.dismiss();
if (result != null){
this.finish();
}
else
{
Descargar.this.finish();
}
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
HttpURLConnection connection = null;
for (i=0; i< sUrl.length; i++) {
try {
URL url = new URL(sUrl[i]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
fOut = openFileOutput(i+".json",MODE_PRIVATE);
//fOut = new FileOutputStream("/aste/tiempobilbao.json");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
fOut.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (fOut != null)
fOut.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
}
return null;
}
}
If the file exist, delete it first.
you can delete file before starting download with below code :
File myFile = new File(fileName);
if(myFile.exists())
myFile.delete();