I have a question on using AsyncTask class provided by Android sdk. I am starting a task in my code from the activity whose work is to send emails periodically (as per the specified time). I restart the task in onPostExecute(). It does send email periodically but after some time emails stop going. Does pressing the back button have any impact on it ?
I was going through the following link on AsyncTask and found that AsyncTask needs to be refreshed after the activities' orientation changes or is out of focus. Do I need to handle this separately ? Do i need to refresh the context everytime the activity is out of focus or its orientation changes ? There are certain DB operations I am doing based on context.
Here is my AsyncTask code :
public class SendEmailTask extends AsyncTask<String, Void, String> {
private static final String LOG_TAG = "EmailTask";
private static final int MESSAGE_SENT = StringConstants.CONSTANT_YES_FLAG;
private Context context;
public SendEmailTask(Context context) {
this.context = context;
}
@Override
protected String doInBackground(String... time) {
// String message = "Message sent at ";
try{
//DB operations
Validator validator = new Validator(context);
int emailInterval = validator.validForSendingEmail(settingsMap);
String emailId = settingsMap.get(DBSetting.COLUMN_EMAILID);
String emailPwd = settingsMap.get(DBSetting.COLUMN_EMAIL_PWD);
if (emailId != null && emailPwd != null && emailInterval > 0) {
Thread.sleep((Integer.valueOf(emailInterval) * 60000));
// TODO: formatting of email body
DALLog dalLog = DALLog.getDALLogInstance();
dalLog.init(context);
GMailSender sender = new GMailSender(emailId, emailPwd);
sender.sendMail("Mail From Auto responder",
result, emailId,
emailId);
dalLog.close();
}
return null;
}
catch (NumberFormatException e) {
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (InterruptedException e) {
e.printStackTrace();
Log.d(LOG_TAG, e.getMessage());
}
catch (Exception e) {
Log.d(LOG_TAG, e.getMessage());
}
return null;
}
@Override
protected void onPostExecute(String result) {
//DB operations
Validator validator = new Validator(context);
int emailInterval = validator.validForSendingEmail(settingsMap);
// Start EmailTask thread if not started already
SendEmailTask emailTask = new SendEmailTask(context);
if (emailTask.getStatus() != AsyncTask.Status.RUNNING) {
emailTask.execute(new String[]{});
}
}
}
When you start up a task that uses the context of an Activity, that task is being run in the same life cycle as the Activity. When the Activity is destroyed, its context is going to be lost with it, without a valid context the task will fail.
If you want a context that is available for the lifetime of the application, you should use getApplicationContext() which does not require an active Activity (and shouldn't be used to modify an Activity as a result).
Incorrect usage can also cause issues with garbage collection - objects being left floating around.
As has been mentioned in the comments section of your question, the best way to go forward, if you want to be able to run an AsyncTask whilst the application is not in the foreground (that is, in the background without the user's input required), is to create a Service which the AsyncTask can run within.
A Service will have its own context you can use, and you can bind the Service to your Activity if you want direct communication between the two.
For more info on Services see this Android Developer Article which provides an overview of their use
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With