I am working on an Android Application , Here I am working with a ProgressBar , for which I am using runOnUiThread() to make VISIBLE/GONE from doInBackground() method of AsyncTask , I did not find other places except doInBackground() suitable to make VISIBLE/GONE ProgressBar to meet the UI requirement .
In this coding scenario ProgressBar is visible but not rotating , It is rotating when I make visible ProgressBar from onCreate() method of Activity .
I am not getting why it is happening , I visited few posts on Stackoveflow , they are saying that UI thread is not able to rotate ProgressBar since it is available in processing other tasks so as a fix I am not able to find other way to make it working .
So please help me what should be the fix of this issue .
Here is the code which I am using to make VISIBLE/GONE ProgressBar .
#Override
protected String doInBackground(String... f_url) {
int count;
try {
zipfileName = f_url[1];
fUrl3 = f_url[2];
if (fUrl3.equals("DontDownloadZip")) {
return "DownloadSuccess";
} else {
Log.d("Downloading ", zipfileName);
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// Hide ProgressBar after server connection .
runOnUiThread(new Runnable() {
#Override
public void run() {
tipLayout.setVisibility(GONE);
}
});
// Code to download a file .
int lenghtOfFile = conection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream(),
8192);
OutputStream output = new FileOutputStream(MyBooks.screen
.getFilesDir().getAbsolutePath()
+ "/BookZips/"
+ f_url[1]);
byte data[] = new byte[1024];
long total = 0;
int counter = 0;
while ((count = input.read(data)) != -1) {
counter++;
total += count;
// Display ProgressBar when percentage is 99 .
if ((int) ((total * 100) / lenghtOfFile) == 99) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!identifier1.equals("BookZips9Download"))
tipLayout.setVisibility(VISIBLE);
}
});
}
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
android.os.FileUtils.setPermissions(MyBooks.screen
.getFilesDir().getAbsolutePath()
+ "/BookZips/"
+ f_url[1], FileUtils.S_IRWXU | FileUtils.S_IRWXG
| FileUtils.S_IROTH | FileUtils.S_IWOTH
| FileUtils.S_IXOTH, -1, -1);
}
} catch (Exception e) {
e.printStackTrace();
return "DownloadFailed";
}
return "DownloadSuccess";
}
Try to add following line in your manifest file:
<activity android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
>
Here, Replace ".MainActivity" to that activity where you used your async task code.
Make the progress bar visible in onPreExecute method and hide your progress bar on onPostExecute method. this should resovle your problem as such you would not need to use runOnUIThread method
Do not put your UI code on doInBackground() (doInBackground() is executed on a background thread). This will crash because you are trying to access a UI thread's object (in this case, View object) in another thread.
If you want to update your progress bar:
In doInBackground(), trigger this method
publishProgress(Integer... progress)
#Override
protected String doInBackground(String... f_url) {
// Do your background tasks
publishProgress(progress);
}
Override onProgressUpdate() method (You can safely access View objects here)
protected void onProgressUpdate(Integer... progress) {
// Updates your progress bar here
}
Related
I am downloading some files from the internet using the async task. For this matter I know it is very relevant to show to the user the progress so far. All my implementation of downloading the file is very successful, but the only problem is with the progress dialog, this shows a 0 percent even when the download command has been started.
This is how i do it
// Show Dialog Box with Progress bar
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type:
prgDialog = new ProgressDialog(this);
prgDialog.setMessage("Downloading Mp3 file. Please wait...");
prgDialog.setIndeterminate(false);
prgDialog.setMax(100);
prgDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
prgDialog.setCancelable(false);
prgDialog.show();
return prgDialog;
default:
return null;
}
}
// Async Task Class
class DownloadMusicfromInternet extends AsyncTask<String, String, String> {
// Show Progress bar before downloading Music
#Override
protected void onPreExecute() {
super.onPreExecute();
// Shows Progress Bar Dialog and then call doInBackground method
showDialog(progress_bar_type);
}
// Download Music File from Internet
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// Get Music file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(),10*1024);
// Output stream to write file in SD card
OutputStream output = new FileOutputStream(f_url[1]);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// Publish the progress which triggers onProgressUpdate method
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// Write data to file
output.write(data, 0, count);
}
// Flush output
output.flush();
// Close streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
// While Downloading Music File
protected void onProgressUpdate(String... progress) {
// Set progress percentage
prgDialog.setProgress(Integer.parseInt(progress[0]));
}
// Once Music File is downloaded
#Override
protected void onPostExecute(String file_url) {
// Dismiss the dialog after the Music file was downloaded
dismissDialog(progress_bar_type);
Toast.makeText(getApplicationContext(), "Download complete, playing Music", Toast.LENGTH_LONG).show();
}
}
Please how can i make the progress move according as the downloading time is moving. Thanks for helping.
UPDATE
I think this problem is not the same as the one referred to be duplicate, the problem with mine after research is coming from the int lenghtOfFile = conection.getContentLength();
The progress is not moving because the getContentLength() always returns -1 because its unable to get the file size from the server. I have seen a lot of questions like this which are not answered. Please is there a way out? I would be grateful to know. Thanks Advance
As you said in a comment, getContentLength() is returning -1. This causes your progress updates to always be negative, which means the progress bar never advances. That's why it's not moving as you expect.
According to the javadoc, getContentLength() returns -1 when there is no content length header or for some reason can't be parsed as a number. In this case, you can't provide a progress meter based on a size of the file being downloaded.
If your progress bar is set to indeterminate, then there is no need to call prgDialog.setProgress(Integer.parseInt(progress[0]));. That's probably the reason why is not showing progress.
Call prgDialog.setIndeterminate(true) when the download starts, and then prgDialog.setIndeterminate(false) when it finishes. Avoid calling setProgress when you are using an indeterminate progress bar.
EDIT: Correcttion: from offical docs calling setProgress does nothing if the bar is in indeterminate mode.
Also, you said you are setting indeterminate to true, but in the onCreateDialog method I see prgDialog.setIndeterminate(false);.
I'm not really sure what goes wrong with my code or structure. I wanted to use AsyncTask to download images and display out the progress bar at the mean time. But I tried out a few different way of doing it. It still failed and no idea what's wrong with it. My structure flow is
ContentID is a string array that stores the content ID of the Images.
Primary Issue: It managed to download images from the url and store into the phone, but the downloaded images are all the same image. It should be different images, it's not what I expected.
Secondary Issue: The progress bar pop up while the application downloading images, but the progress bar did not update it's progress. It just remains 0% and dismissed after the download completed.
I wanted to know what causes primary and secodary issue as i mentioned. Please leave a comment or answer if you might know what's wrong with my code. Any help will be appreciated.
if(isSyncSuccess){
SetConstant.IMAGE_EXIST = 1;
pDialog = new ProgressDialog(GalleryScreen.this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setProgress(0);
pDialog.setMax(contentId.length);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
if (contentId.length>0){
Log.i(TAG, "contentid.length:" +contentId.length);
for (int i=0;i<contentId.length;i++){
if(helper.databaseChecking(useremail, contentId[i])){
contentdownload = i;
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];
DownloadFile downloadFile = new DownloadFile();
downloadFile.execute(URL);
}
private class DownloadFile extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... sUrl){
Bitmap bm;
InputStream in;
try{
in = new java.net.URL(sUrl[0]).openStream();
bm = BitmapFactory.decodeStream(new PatchInputStream(in));
File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
Log.i(TAG,"storage:" +storage);
Log.i(TAG,"storage:" +storage.getAbsolutePath());
if(!storage.exists()){
storage.mkdirs();
}
String FileName = "/"+SetConstant.CONTENT_ID+".jpg";
FileOutputStream fos = new FileOutputStream(storage + FileName);
bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);
String filepath = storage + FileName;
File filecheck = new File (filepath);
long fileSize = filecheck.length();
fos.flush();
fos.close();
Log.i(TAG, "bm:" +bm);
Log.i(TAG, "fos:" +fos);
Log.i(TAG, "filesize:" +fileSize);
Log.i(TAG, "filepath:" +filepath);
}
catch(IOException e1){
e1.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress){
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
protected void onPostExecute(String result){
super.onPostExecute(result);
pDialog.dismiss();
}
}
Edit
Now the application able to download images according and the progress bar is working as well! But I got another issue is how to return error message when the application failed to complete the download. Currently when the application failed to download it will crash. I believed that I should not run it inside the doInBackground side. But where else can I do the checking? Any idea how to return as an error message and request for the user to retry instead of crashing the application?
You never called onProgressUpdate during your doInBackGround(...). Please note that running multiple instances of AsyncTask is a bad idea. Here is what I suggest:
if(isSyncSuccess){
SetConstant.IMAGE_EXIST=1;
pDialog=new ProgressDialog(GalleryScreen.this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setProgress(0);
pDialog.setMax(contentId.length);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
new DownloadFile().execute();
}
private class DownloadFiles extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
Bitmap bm;
InputStream in;
if (contentId.length > 0) {
for (int i = 0; i < contentId.length; i++) {
if (helper.databaseChecking(useremail, contentId[i])) {
contentdownload = i;
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT + contentId[i];
//YOUR INTRESTING LOOP HERE.
publishProgress(30);
//SOME INTRESTING NUMBER FOR PROGRESS UPDATE
}
}
try {
in = new java.net.URL(sUrl[0]).openStream();
bm = BitmapFactory.decodeStream(new PatchInputStream(in));
File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
Log.i(TAG, "storage:" + storage);
Log.i(TAG, "storage:" + storage.getAbsolutePath());
if (!storage.exists()) {
storage.mkdirs();
}
String FileName = "/" + SetConstant.CONTENT_ID + ".jpg";
FileOutputStream fos = new FileOutputStream(storage + FileName);
bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);
String filepath = storage + FileName;
File filecheck = new File(filepath);
long fileSize = filecheck.length();
fos.flush();
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute () {
super.onPreExecute();
pDialog.show();
}
#Override
protected void onProgressUpdate (Integer...progress){
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
protected void onPostExecute (String result){
super.onPostExecute(result);
pDialog.dismiss();
}
}
}
Of course this code don't run and you need to fix the scopes. But what I am trying to suggest is that your loop should be in doInBackGround(...), you should only have 1 instance of AsyncTask at given time for this case, and call the onProgressUpdate().
Primary issue :
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];
Here, you are facing trouble. As #Sofi Software LLC's answer, you are using a global variable, whose value is being changed by the main thread, in another thread.
Secondary Issue :
If you want a progress bar to update, you have to update its value;
it doesn't update itself.
You do need to download the image in AsyncTask (Downloading from URL). Effectively to achieve your functionality, you need to do
Create AsyncTask to download your image (implement download in
doInBackground()), also have a boolean (say isImageDownloaded) to
track if the image is successfully downloaded in postExecute().
Don't forget to also show your progress bar before initiating the
download
Execute your AsyncTask to initiate download
Create extension of android.os.CountDownTimer to countdown a minimum
time
On the method onFinish() check the boolean that you track, if it is
false then you cancel the AsyncTask and throw the toast/dialog that
you intended
Running multipule instance of AsyncTask is not a good idea, so do one after another. You can execute your AsyncTask's on an Executor using executeOnExecutor().To make sure that the threads are running in a serial fashion please use: SERIAL_EXECUTOR.
Following resources may help you #
If you need to download an image, show progress bar and load in a imageview
https://github.com/koush/UrlImageViewHelper
http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.html
http://blog.blundell-apps.com/imageview-with-loading-spinner/
If you need to download multiple files (here, for images) using AsyncTask
Problem with downloading multiple files using AsyncTask
How to get back the task completion status in AsyncTask
Implement Progress Bar for File Download in Android
EDIT:
From http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.html
new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
.execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png"); }
public void onClick(View v) {
startActivity(new Intent(this, IndexActivity.class));
finish();
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
} }
From Image download in an Android ImageView and Progressbar implementation
// note that you could also use other timer related class in Android aside from this CountDownTimer, I prefer this class because I could do something on every interval basis
// tick every 10 secs (or what you think is necessary)
CountDownTimer timer = new CountDownTimer(30000, 10000) {
#Override
public void onFinish() {
// check the boolean, if it is false, throw toast/dialog
}
#Override
public void onTick(long millisUntilFinished) {
// you could alternatively update anything you want every tick of the interval that you specified
}
};
timer.start()
In the following line:
SetConstant.CONTENT_ID = contentId[i];
You're setting a global variable to a value, then you create a string url based on that same value and pass it to the AsyncTask. That executes, and then when it is done downloading, it create a file whose name is based on the global variable SetConstant.CONTENT_ID.
In other words, you are using a global variable, whose value is being changed by the main thread, in another thread. Don't do this, as you will get all kinds of weird problems due to the different threads updating at different times.. Pass in the value or the name of the output file to the AsyncTask. You can do that in a constructor for DownloadFile, and stash the value in a field.
If you want a progress bar to update, you have to update its value; it doesn't update itself. Call AsyncTask.publishProgress during the task (in doInBackground) and implement onProgressUpdate to update the progress dialog.
[EDIT: onProgressUpdate is indeed called in the UI thread.]
First create a separated class which allows you to reach to image address
like following:
public class ImageDownloader extends AsyncTask {
#Override
protected Bitmap doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(inputStream);
return myBitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Then get access to that class (through a method called by a button) by creating an object and execute the Bitmap task like following :
public class MainActivity extends Activity {
ImageView downloadedImg;
public void downloadImage(View view) {
ImageDownloader task = new ImageDownloader();
Bitmap myImage;
try {
myImage = task.execute("YOUR IMAGE ADDRESS ........").get();
downloadedImg.setImageBitmap(myImage);
} catch (Exception e) {
e.printStackTrace();
}
}
Do NOT forget to:
1 - define the imageView in onCreat method ==> downloadedImg = (ImageView) findViewById(R.id.imageView);
2 - to link the method you've created by a button in user interface ==> (public void downloadImage(View view){})
3 - ask for permission in manifest file
While uploading multiple image at a time i want to show progress bar which show the progress bar in statusbar notification area with the info 1/5 and 2/5 and so on. where 1 is no of image uploaded and 5 is total no of image to be uploaded.
here i am able show progress bar in notification area. can any one suggest me, how to calculate no of image uploaded(finished) to show in progress bar (like 1/5)update. thanks in advance.
For making more clear
i have a asyntask which upload a single image to server. but i am not able to do
1> calculate size of total image (say for example 5 image)
2>how to find no of image uploaded in total 5 image
private class FileUploadTask extends AsyncTask<Object, Integer,String> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
dialog.setMessage("Uploading...");
dialog.setIndeterminate(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.show();
}
#Override
protected String doInBackground(Object... arg0) {
try {
File file = new File("/mnt/sdcard/DCIM/100MEDIA/IMAG0149.jpg");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[(int) file.length()];
fileInputStream.read(bytes);
fileInputStream.close();
URL url = new URL("http://android.com.bd/form.php");
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
OutputStream outputStream = connection.getOutputStream();
int bufferLength = 1024;
for (int i = 0; i < bytes.length; i += bufferLength) {
int progress = (int)((i / (float) bytes.length) * 100);
Log.i("progress",progress+"dfdf");
publishProgress(progress);
if (bytes.length - i >= bufferLength) {
outputStream.write(bytes, i, bufferLength);
} else {
outputStream.write(bytes, i, bytes.length - i);
}
}
publishProgress(100);
outputStream.close();
outputStream.flush();
InputStream inputStream = connection.getInputStream();
// read the response
inputStream.close();
return "ok";
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
dialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
Log.v("sds", result);
try {
dialog.dismiss();
} catch(Exception e) {
}
}
}
Take a look at this TL;DR blog post/tutorial. You should be able to do something similar. You'll want to use a ProgressDialog, updating its state using an ASyncTask. If you're already using an ASyncTask for your image upload, you already have the pieces in place.
http://toolongdidntread.com/android/android-multipart-post-with-progress-bar/
Also take a look at this SO question - Download a file with Android, and showing the progress in a ProgressDialog. Your question has been answered before. You'll just need to adapt the solution to display the progress bar at 1/5, 2/5, etc by customizing onProgressUpdate. I haven't tested this code, but I'd imagine something along these lines will allow you to display the progress incrementally like you want.
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
if (progress[0] < 20) {
mProgressDialog.setProgress(0);
} else if (progress[0] < 40) {
mProgressDialog.setProgress(20);
}
else if (progress[0] < 60) {
mProgressDialog.setProgress(40);
}
else if (progress[0] < 80) {
mProgressDialog.setProgress(60);
}
else if (progress[0] < 100) {
mProgressDialog.setProgress(80);
}
else if (progress[0] == 100) {
mProgressDialog.setProgress(100);
}
}
Where are your images? you have to do like
File fav = new File(Environment.getExternalStorageDirectory().getPath());
File[] filesav = fav.listFiles();
for (int i = 0; i < filesav.length; i++) {
inside you send your pictures and count
}
the variable i is your image number and filesav.length is your total image number
Well, it really depends on how you download you images ?
What I would advice is to create an instance (singleton) of some DownloadManager class, which would count and manage the number of started and finished download. This instance will be used to create new downloads, and will be notified each time a download is finished. When notified, it could then update the progress bar.
But this is a very generic answer. Cannot do better without more informations on how you currently do the downloads (are they done in separate threads ? Are they sequential or parallel ?...)
I am using this example to download a file from a server using AsycTask and to show the downlaod progress in a notification bar. I just modified the doInBackground method in order to downoad my file:
#Override
protected Void doInBackground(String... Urls) {
//This is where we would do the actual download stuff
//for now I'm just going to loop for 10 seconds
// publishing progress every second
try {
URL url = new URL(Urls[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());
OutputStream output = new FileOutputStream( _context.getFilesDir() + "/file_name.apk");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count ;
// publishing the progress....
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
protected void onPreExecute() {
// Create the notification in the statusbar
mNotificationHelper.createNotification();
}
protected void onPostExecute(Void result) {
// The task is complete, tell the status bar about it
mNotificationHelper.completed();
}
protected void onProgressUpdate(Integer... progress) {
// This method runs on the UI thread, it receives progress updates
// from the background thread and publishes them to the status bar
mNotificationHelper.progressUpdate(progress[0]);
}
Everything is going ok except that I cannot pull down the notification bar. Why?
Following is picked from the comments.
can you please put an sleep(1000) method before publishProgress and
check. just a guess
-
yes, it works, but the download is slowing
Hope you understood the problem. Since you are updating the Notification bar very frequently, you cant be able to pull it down. By increasing the chunk size of data or by updating the progress bar on every 4 or more kb instead of 1kb, you can avoid this problem.
Above will not slow down the data download.
You should override onProgressUpdate method to update your UI.
I made an app that downloads videos from our server.
The issue is:
When i cancel the downloading i call:
myAsyncTask.cancel(true)
I noticed, that myAsyncTask doesn't stops on calling cancel... my ProgressDialog still goes up and its like jumping from status to status showing me that each time I cancel and start again an AsyncTask by clicking the download button, a new AsyncTask starts...
Each time I click download.. then cancel, then again download a separate AsyncTask starts.
Why is myAsynTask.cancle(true) not cancelling my task ? I don't want it anymore on the background. I just want to completely shut it down if I click cancel.
How to do it ?
E D I T:
Thanks to gtumca-MAC, and the others who helped me did it by:
while (((count = input.read(data)) != -1) && (this.isCancelled()==false))
{
total += count;
publishProgress((int) (total * 100 / lenghtOfFile));
output.write(data, 0, count);
}
Thanks!!!
AsyncTask does not cancel process on
myAsynTask.cancel(true)
For that you have to stop it manually.
for example you are downloading video in doInBackground(..) in while/for loop.
protected Long doInBackground(URL... urls) {
for (int i = 0; i < count; i++) {
// you need to break your loop on particular condition here
if(isCancelled())
break;
}
return totalSize;
}
Declare in your class
DownloadFileAsync downloadFile = new DownloadFileAsync();
then On Create
DownloadFileAsync downloadFile = new DownloadFileAsync();
downloadFile.execute(url);
in Your Background ()
if (isCancelled())
break;
#Override
protected void onCancelled(){
}
and you can kill your AsyncTask by
downloadFile.cancel(true);
When you start a separate thread(AyncTask) it has to finish. You have to manually add a cancel statement to your code inside the AsyncTask.
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
Checkout more in the documentation: http://developer.android.com/reference/android/os/AsyncTask.html
I have been researching from the last 2 weeks and I don't get to know that how we kill the Async operation manually. Some developers use BREAK; while checking in for loop. But on my scenario I am not using the loop inside of background thread.
But I have got to know how it woks its a stupid logic but works perfectly fine.
downloadFile.cancel(true); //This code wont work in any case.
Instead of canceling and doing so much work on background thread turn off the wifi programmatically
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(false);
where do you want to kill the operation and turn on it where do you need that.
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);
What happens is your try block jumps in to the IOException killing the background tasks.
You better use vogella asyncTask library which have a lot of features like priority and canceling background task. And a great tutorial or using it is here
You can use this code. I am downloading a OTA file as follow:
static class FirmwareDownload extends AsyncTask<String, String, String> {
public String TAG = "Super LOG";
public String file;
int lenghtOfFile;
long total;
#Override
protected String doInBackground(String... f_url) {
try {
int count;
Utilies.getInternet();
URL url = new URL(f_url[0]);
URLConnection connection = url.openConnection();
connection.connect();
lenghtOfFile = connection.getContentLength();
mProgressBar.setMax(lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream(), 8192);
String fileName = f_url[0].substring(f_url[0].lastIndexOf("/"), f_url[0].length());
File root = Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + fileName);
Log.d(TAG, "trying to download in : " + dir);
dir.getAbsolutePath();
OutputStream output = new FileOutputStream(dir);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
if (isCancelled())
break;
total += count;
mProgressBar.setProgress(Integer.parseInt("" + total));
Log.d("Downloading " + fileName + " : ", " " + (int) ((total * 100) / lenghtOfFile));
mPercentage.post(new Runnable() {
#Override
public void run() {
mPercentage.setText(total / (1024 * 1024) + " Mb / " + lenghtOfFile / (1024 * 1024) + " Mb");
}
});
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
//new InstallHelper().commandLine("mkdir data/data/ota");
File fDest = new File("/data/data/ota/" + fileName);
copyFile(dir, fDest);
FirmwareInstaller fw = new FirmwareInstaller();
fw.updateFirmware();
} catch (Exception a) {
System.out.println("Error trying donwloading firmware " + a);
new InstallHelper().commandLine("rm -r data/data/ota");
dialog.dismiss();
}
return null;
}
}
So, If you want to cancel, just use this code:
fDownload.cancel(true);
I have used with success inside an activity with TextView onclick ...
//inside the doInBackground() ...
try {
while (true) {
System.out.println(new Date());
//should be 1 * 1000 for second
Thread.sleep(5 * 1000);
if (isCancelled()) {
return null;
}
}
} catch (InterruptedException e) {
}
and in my onCreate() ...
//set Activity
final SplashActivity sPlashScreen = this;
//init my Async Task
final RetrieveFeedTask syncDo = new RetrieveFeedTask();
syncDo.execute();
//init skip link
skip_text = (TextView) findViewById(R.id.skip_text);
skip_text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//cancel Async
syncDo.cancel(true);
//goto/start another activity
Intent intent = new Intent();
intent.setClass(sPlashScreen, MainActivity.class);
startActivity(intent);
finish();
}
});
and my xml TextView element ...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/skip_text"
android:layout_marginTop="20dp"
android:text="SKIP"
android:textColor="#color/colorAccent"/>