I am making an app which sends update to web server when a songs starts playing...I do the the web server update through asynctask however some times some information gets skipped and some infos are sent repeatedly. In some case asyntask remain in running state making it not executing after that. Main thread works good.
I declared the instance like this in MainActivity
private static AsyncTask<Void, Void, Void> mTask = null;
code for Asynctask is
private class SendingData extends AsyncTask<Void,Void,Void>{
#Override
protected void onPreExecute(){
//some task
}
protected void onPostExecute(Void params){
Log.d("Tesing","After Post");
super.onPostExecute(params);
}
#Override
protected Void doInBackground(Void... arg0) {
sendPost();
return null;
}
}
My call to asynctask when a new song changes in main thread. This is a repetitive call
if(mTask.getStatus() == AsyncTask.Status.FINISHED){
// My AsyncTask is done and onPostExecute was called
Log.d("AsyncTask Status","Finished");
mTask = new SendingData();
mTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}else if(mTask.getStatus() == AsyncTask.Status.PENDING){
Log.d("AsyncTask Status","Pending");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
You declared your AsyncTask as static variable. This means that your references will get mixed up, i.e. when you start a new AsyncTask, you will overwrite the previous reference with a new one.
Related
I'm having trouble with AsyncTask running multiple methods in doInBackground. this is my AsyncTask code:
public class FETCHDATA extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
pdialog = new ProgressDialog(getContext());
pdialog.setTitle("Please Wait");
pdialog.setMessage("Fetching data...");
pdialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
try{
method1();
method2();
method3();
method4();
method5();
method6();
method7();
}catch (Throwable e){
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void aVoid) {
if (pdialog.isShowing()){
pdialog.dismiss();
}
}
Instead running and waiting the first method is done, the doInBackground proceeds to the next method. and the ProgressDialog dismiss by one second.
Note
Every Method will get data from our API and save it on my SQLiteDatabase .
QUESTION
How can i execute my methods when the first method has finished getting and saving data before moving to the second methods.
Maybe you have to create multiples AsyncTask and whenever the first method finish, communicate it with returning a boolean instead of void instance here ---> extends AsyncTask.
This is weird.
I assume that your methodX() are asynchronous call?
In that case, you can use Thread.join() or CountDownLatch.
You are violating usage of async task. Async task is designed for doing short async operations and update the UI easily before, during and after, It is not for doing 7 network & Sqlite operations at once.
You can read more here, : https://developer.android.com/reference/android/os/AsyncTask
So you need to implement some kind of job for yourself to execute these operations at once or use some popular libraries like Retrofit.
If you insist to use async task, since an async task need to be executed from UI thread, you need to create new async task an execute it from onPostExecute every time when it is done and you of course need to pass a param(a counter or something) to doInBackground to know which method should be called.
You can put a counter with a switch case statment in the doInBackground in wich you choose the methode to execute and then in the onPostExecute call new FETCHDATA().execute() recursively
EDIT : working code ( i forgot break; after case;)
int counter = 1; // global
class Fetchdata extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... voids) {
try {
switch (counter) {
case 1:
method1();
break;
case 2:
method2();
break;
case 3:
method3();
break;
case 4:
method4();
break;
case 5:
method5();
break;
default:
cancel(true);
counter = 1;
break;
}
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
counter+=1;
Log.d(TAG, "onPostExecute: "+counter);
// cancel(true);
new Fetchdata().execute();
}
}
void method1(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode1: coucou");
}
void method2(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode2: ");
}
void method3(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode3: ");
}
void method4(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode4: ");
}
void method5(){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "methode5: ");
}
I think the problem is that your all methods or some methods already runs on a separate thread . So whenever you call a method which already runs on separate thread doInBackground() i.e current thread will not wait for it and continue the execution.
Apart from that The way you put try-catch is not a proper way to do it . Also if you want to call several threads one after another you should go with ThreadPoolExecuter.
If you are not using a Network library To make API calls you can use RetroFit.
I am developing an application in which what I done is:
In onCreate() I first called a Async Task and then write a thread as:
new LoadDataBase().execute();
// New Thread call.
new Thread() {
// Running Thread.
public void run() {
int count=0;
while (count<5){
try{
Thread.sleep(500);
count++;
}catch(Throwable e){
e.printStackTrace();
}
}
Intent intent = new Intent(ActivityOne.this,ActivityTwo.class);
startActivity(intent);
finish();
}
}.start();
My Async Task Code is as follows:
private class LoadDataBase extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... arg0) {
// Create data base from assets folder.
DataBaseHelper dataBaseHelper = new DataBaseHelper(getApplicationContext());
try {
dataBaseHelper.createDataBase();
} catch (IOException e) {
e.printStackTrace();
}
// Closing the Data base.
dataBaseHelper.close();
return "";
}
#Override
protected void onPostExecute(String result) {}
}
But the issue is that my thread is not working properly. Means I want that the Activity one should wait for some time then activity two invoke. But it is not happing.
As I run my app, activity one is visible for fraction on second and activity two is occurs. It happens so fast that the user is not able to find that activity one is there in the app or not. But the other functionality is working fine.
Now what should I do now to hold my activity one. I don't want to implement progress dialog in Async Task because I already implemented it in XML file.
Please guide me
In onPostExecute(String result) Method, Write waiting time code using Handler...
I've seen several other post about canceling an AsynTask, but I don't think any of them resolves the issues. Imagine this scenario:
public class TestTask extends AsyncTask<Void, Void, Object> {
#Override
protected void onCancelled(Object result) {
running = false;
Log.i("Test", "onCancelled");
}
#Override
protected Object doInBackground(Void... params) {
try {
Log.i("Test", "cancelling");
cancel(true);
Thread.sleep(5000);
Log.i("Test", "Past sleep");
} catch (InterruptedException e) {
Log.i("Test", "InterruptedException", e);
}
return null;
}
}
Imagine I'd like to cancel this long 20 second request in the middle of a download, for example if the server is responding slow to a json request. So the Thread.sleep(5000) could be a HttpGet request that I'd like to cancel. However the cancel method is marked as final so I can't override it and call get.abort(). The onCancel hook happens after the doInBackground and back on the UI thread. Checking for isCancel won't do me any good once the HttpGet request has started.
The way I solve this is to make an abort() method on my AsynTask and just call that.
public void abort() {
get.abort();
cancel(true);
}
but this seems to go against the Android grain a bit. Is there a better way to cancel the request?
In the docs for HttpGet, there is no mention of thread safety, so calling abort() the way you described will probably lead to undesired results (at best). What you could do is pass an HttpGet object in the constructor for your AsyncTask, or via a setter (as long you do this before you call AsyncTask.execute()).
You would have to check periodically inside of doInBackground() if the task has been cancelled:
#Override
protected Object doInBackground(Void... params) {
// start GET request
try {
Log.i("Test", "cancelling");
cancel(true);
Thread.sleep(5000);
Log.i("Test", "Past sleep");
if ( this.isCancelled() ) {
// abort GET request and/or stop doing other work
return null;
}
else {
// do what ever work you need to
}
} catch (InterruptedException e) {
Log.i("Test", "InterruptedException", e);
}
return null;
}
Source.
You can always call AsyncTask.cancel(true) whenever you feel the task should be stopped (AsyncTask.cancel())
I am not sure if this is applicable or not, but you could create another thread using an executor service that executes the download-task and keep checking for isCancelled() inside doInBackground() or until the future object returns, whichever happens first:
#Override
protected Object doInBackground(Void... params)
{
Callable<Void> downlaodTask = new Callable<Void>()
{
#Override
public Void call() throws Exception
{
// download task here
return null;
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(downlaodTask);
while(true) // check every second
{
try
{
future.get(1, TimeUnit.SECONDS); // wait until the download task finishes with 1 second as a timeout
break;
}
catch(TimeoutException e)
{
if(isCancelled())
{
executor.shutdownNow(); // or abort() or both
break;
}
}
}
return null;
}
I have an inner class that downloads some images from the server. The problem is that the ProgressDialog does not dismiss() onPostExecute() method and don't understand why.
I understand that the progress dialog should be shown onPreExecute() method, and the after the code from the doInBackground() finished , in the onPostExecute() method the dialog should be dismiss. Do you have any idea what i am doing wrong here? Thank you.
/**
* Download images from server
*/
public class DownloadAsyncTask extends AsyncTask<Void, Integer, Void> {
private ProgressDialog mDialog;
// execution of result of Long time consuming operation
protected void onPostExecute(Void result) {
// progressDialog.show();
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
// Things to be done before execution of long running operation.
protected void onPreExecute() {
mDialog = ProgressDialog
.show(ImagesActivity.this, getString(R.string.pleasewait),
getString(R.string.loading));
}
// perform long running operation operation
protected Void doInBackground(Void... params) {
System.out.println("doInBackground loading.." + id);
String tempPath = FileUtils.createTempFile(id);
for (int i = 0; i < imagePaths.size(); i++) {
imagePaths.get(i).trim();
try {
Bitmap imgTemp;
imgTemp = FileUtils.downloadBitmapFromURL(id,
imagePaths.get(i), tempPath);
System.out.println("imgTemp: " + imgTemp);
if (imgTemp != null) {
// save image on sdcard.
// compress it for performance
Bitmap img = Bitmap.createScaledBitmap(imgTemp, 90, 80,
true);
imgTemp.recycle();
FileUtils.saveDataToFile(img, tempPath,
imagePaths.get(i));
} else {
continue;
}
} catch (IOException e) {
e.printStackTrace();
mDialog.dismiss();
}
}
Looper.prepare();
mDialog.dismiss();
return null;
}
/*
* Things to be done while execution of long running operation is in
* progress.
*/
protected void onProgressUpdate(Integer... values) {
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
}
actually what you are trying to do is to access the UI Thread from another thread and that is not possible , in your case you are using AsyncTask class enables proper and easy use of the UI thread without having to manipulate threads and/or handlers. use onPostExecute(Result) to access the UI Thread.
so this should work
protected void onPostExecute(Void result) {
progressDialog.show();
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
I've struggled with this same problem for quite a while. Here is how I got it solved, take a look at this part of the documentation:
A dialog is always created and displayed as a part of an Activity. You
should normally create dialogs from within your Activity's
onCreateDialog(int) callback method. When you use this callback, the
Android system automatically manages the state of each dialog and
hooks them to the Activity, effectively making it the "owner" of each
dialog
Note: If you decide to create a dialog outside of the onCreateDialog()
method, it will not be attached to an Activity. You can, however,
attach it to an Activity with setOwnerActivity(Activity).
from: http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
This is an example of what you have to set on your activity:
#Override
protected void onPrepareDialog(int id, Dialog dialog)
{
//This doesn't do anything
if (id == DIALOG_PROGRESS_ID) {
((ProgressDialog)dialog).setIndeterminate(true);
}
super.onPrepareDialog(id, dialog);
}
#Override
protected Dialog onCreateDialog(int id)
{
if (id == DIALOG_PROGRESS_ID) {
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Loading");
dialog.setCancelable(false);
dialog.setIndeterminate(true);
return dialog;
}
return null;
}
You can then call
myActivity.showDialog(myActivity.DIALOG_PROGRESS_ID), myActivity.dismissDialog(myActivity.DIALOG_PROGRESS_ID) from any where as long as you have a reference to your activity instance.
Use a handler and onPostExecute() send the handler msg to dismiss the progress dialog.
You can get help from this link ProgressDialog dismissal in android
Your code is working fine but can you check that control are reaching in Post onPostExecute() method I have tried as
package com.alarm.activity;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
public class AlarmManagerActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set up main content view
setContentView(R.layout.main);
new DownloadAsyncTask().execute();
}
/**
* Download images from server
*/
public class DownloadAsyncTask extends AsyncTask<Void, Integer, Void> {
private ProgressDialog mDialog;
// execution of result of Long time consuming operation
#Override
protected void onPostExecute(Void result) {
// progressDialog.show();
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
// Things to be done before execution of long running operation.
#Override
protected void onPreExecute() {
mDialog = ProgressDialog.show(AlarmManagerActivity.this, "Hello", "Test");
}
// perform long running operation operation
#Override
protected Void doInBackground(Void... params) {
//System.out.println("doInBackground loading.." + id);
/* String tempPath = FileUtils.createTempFile(id);
for (int i = 0; i < imagePaths.size(); i++) {
imagePaths.get(i).trim();
try {
Bitmap imgTemp;
imgTemp = FileUtils.downloadBitmapFromURL(id, imagePaths.get(i), tempPath);
System.out.println("imgTemp: " + imgTemp);
if (imgTemp != null) {
// save image on sdcard.
// compress it for performance
Bitmap img = Bitmap.createScaledBitmap(imgTemp, 90, 80, true);
imgTemp.recycle();
FileUtils.saveDataToFile(img, tempPath, imagePaths.get(i));
}
else {
continue;
}
}
catch (IOException e) {
e.printStackTrace();
mDialog.dismiss();
}
}
Looper.prepare();
mDialog.dismiss();*/
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/*
* Things to be done while execution of long running operation is in
* progress.
*/
#Override
protected void onProgressUpdate(Integer... values) {
if (mDialog.isShowing()) {
mDialog.dismiss();
}
}
}
}
I think problem in doInbackground() method. I have simply run thread for sleep 5 sec and after control reaches in post() method and dissmiss progress dialog.
I am running remote audio-file-fetching and audio file playback operations in a background thread using AsyncTask. A Cancellable progress bar is shown for the time the fetch operation runs.
I want to cancel/abort the AsyncTask run when the user cancels (decides against) the operation. What is the ideal way to handle such a case?
Just discovered that AlertDialogs's boolean cancel(...); I've been using everywhere actually does nothing. Great.
So...
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
private final ProgressDialog progressDialog;
public MyTask(Context ctx) {
progressDialog = gimmeOne(ctx);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
// actually could set running = false; right here, but I'll
// stick to contract.
cancel(true);
}
});
}
#Override
protected void onPreExecute() {
progressDialog.show();
}
#Override
protected void onCancelled() {
running = false;
}
#Override
protected Void doInBackground(Void... params) {
while (running) {
// does the hard work
}
return null;
}
// ...
}
If you're doing computations:
You have to check isCancelled() periodically.
If you're doing a HTTP request:
Save the instance of your HttpGet or HttpPost somewhere (eg. a public field).
After calling cancel, call request.abort(). This will cause IOException be thrown inside your doInBackground.
In my case, I had a connector class which I used in various AsyncTasks. To keep it simple, I added a new abortAllRequests method to that class and called this method directly after calling cancel.
The thing is that AsyncTask.cancel() call only calls the onCancel function in your task. This is where you want to handle the cancel request.
Here is a small task I use to trigger an update method
private class UpdateTask extends AsyncTask<Void, Void, Void> {
private boolean running = true;
#Override
protected void onCancelled() {
running = false;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
onUpdate();
}
#Override
protected Void doInBackground(Void... params) {
while(running) {
publishProgress();
}
return null;
}
}
Simple: don't use an AsyncTask. AsyncTask is designed for short operations that end quickly (tens of seconds) and therefore do not need to be canceled. "Audio file playback" does not qualify. You don't even need a background thread for ordinary audio file playback.
The only way to do it is by checking the value of the isCancelled() method and stopping playback when it returns true.
This is how I write my AsyncTask
the key point is add Thread.sleep(1);
#Override protected Integer doInBackground(String... params) {
Log.d(TAG, PRE + "url:" + params[0]);
Log.d(TAG, PRE + "file name:" + params[1]);
downloadPath = params[1];
int returnCode = SUCCESS;
FileOutputStream fos = null;
try {
URL url = new URL(params[0]);
File file = new File(params[1]);
fos = new FileOutputStream(file);
long startTime = System.currentTimeMillis();
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] data = new byte[10240];
int nFinishSize = 0;
while( bis.read(data, 0, 10240) != -1){
fos.write(data, 0, 10240);
nFinishSize += 10240;
**Thread.sleep( 1 ); // this make cancel method work**
this.publishProgress(nFinishSize);
}
data = null;
Log.d(TAG, "download ready in"
+ ((System.currentTimeMillis() - startTime) / 1000)
+ " sec");
} catch (IOException e) {
Log.d(TAG, PRE + "Error: " + e);
returnCode = FAIL;
} catch (Exception e){
e.printStackTrace();
} finally{
try {
if(fos != null)
fos.close();
} catch (IOException e) {
Log.d(TAG, PRE + "Error: " + e);
e.printStackTrace();
}
}
return returnCode;
}
Our global AsyncTask class variable
LongOperation LongOperationOdeme = new LongOperation();
And KEYCODE_BACK action which interrupt AsyncTask
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
LongOperationOdeme.cancel(true);
}
return super.onKeyDown(keyCode, event);
}
It works for me.
I don't like to force interrupt my async tasks with cancel(true) unnecessarily because they may have resources to be freed, such as closing sockets or file streams, writing data to the local database etc. On the other hand, I have faced situations in which the async task refuses to finish itself part of the time, for example sometimes when the main activity is being closed and I request the async task to finish from inside the activity's onPause() method. So it's not a matter of simply calling running = false. I have to go for a mixed solution: both call running = false, then giving the async task a few milliseconds to finish, and then call either cancel(false) or cancel(true).
if (backgroundTask != null) {
backgroundTask.requestTermination();
try {
Thread.sleep((int)(0.5 * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (backgroundTask.getStatus() != AsyncTask.Status.FINISHED) {
backgroundTask.cancel(false);
}
backgroundTask = null;
}
As a side result, after doInBackground() finishes, sometimes the onCancelled() method is called, and sometimes onPostExecute(). But at least the async task termination is guaranteed.
With reference to Yanchenko's answer on 29 April '10:
Using a 'while(running)' approach is neat when your code under 'doInBackground' has to be executed multiple times during every execution of the AsyncTask. If your code under 'doInBackground' has to be executed only once per execution of the AsyncTask, wrapping all your code under 'doInBackground' in a 'while(running)' loop will not stop the background code (background thread) from running when the AsyncTask itself is cancelled, because the 'while(running)' condition will only be evaluated once all the code inside the while loop has been executed at least once. You should thus either
(a.) break up your code under 'doInBackground' into multiple 'while(running)' blocks or
(b.) perform numerous 'isCancelled' checks throughout your 'doInBackground' code, as explained under "Cancelling a task" at https://developer.android.com/reference/android/os/AsyncTask.html.
For option (a.) one can thus modify Yanchenko's answer as follows:
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
//...
#Override
protected void onCancelled() {
running = false;
}
#Override
protected Void doInBackground(Void... params) {
// does the hard work
while (running) {
// part 1 of the hard work
}
while (running) {
// part 2 of the hard work
}
// ...
while (running) {
// part x of the hard work
}
return null;
}
// ...
For option (b.) your code in 'doInBackground' will look something like this:
public class MyTask extends AsyncTask<Void, Void, Void> {
//...
#Override
protected Void doInBackground(Void... params) {
// part 1 of the hard work
// ...
if (isCancelled()) {return null;}
// part 2 of the hard work
// ...
if (isCancelled()) {return null;}
// ...
// part x of the hard work
// ...
if (isCancelled()) {return null;}
}
// ...