I set a timer on AccountActivity.class
to ensure that user does not press home button if not will start the countdown to logout the user or if the user locks his screen.
But now I am facing an issue because of the onPause
method. When my user clicks on a button which invokes the getaccounttask()
method and it will redirect my user to AccountInformationActivity.class
, the onPause
method is activated as well and the timer starts to countdown.
Is there any solution to prevent the onPause
method from counting down or the timer to be cancelled on my AccountInformationActivity.class
?
I tried to do the cancelling of timer before my intent starts but still does not work.
I have tried using handler as well but encountered the same problem, I am still trying to grasp how Android fully works, so your help or solution is deeply appreciated.
public class AccountActivity extends AppCompatActivity {
private Timer timer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
}
private class getaccounttask extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String... urlaccount)
{
StringBuilder result = new StringBuilder();
try
{
//My Codes
}
catch (Exception e)
{
e.printStackTrace();
}
return result.toString();
}
@Override
protected void onPostExecute(String result)
{
Intent intent = new Intent();
intent.setClass(getApplicationContext(), AccountInformationActivity.class);
startActivity(intent);
}
}
@Override
protected void onPause() {
super.onPause();
timer = new Timer();
Log.i("Main", "Invoking logout timer");
LogOutTimerTask logoutTimeTask = new LogOutTimerTask();
timer.schedule(logoutTimeTask, 300000); //auto logout in 5 minutes
}
@Override
protected void onResume() {
super.onResume();
if (timer != null) {
timer.cancel();
Log.i("Main", "cancel timer");
timer = null;
}
}
private class LogOutTimerTask extends TimerTask {
@Override
public void run() {
//redirect user to login screen
Intent i = new Intent(AccountActivity.this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
}
}
Well, the implementation architecture you choose could be improved. I shall come to that later. First apply this quick fix to fix your architecture.
Clearly you want to start a Timer
when you go out of Activity
using home screen. But user can also go out of Activity
by using Intent
to switch to AccountActivity
. This you can track. So keep a boolean flag like shouldNavigate
, initially it should be false
. when onResume
, it should be set to false
, but when getcounttask
goes to onPostExecute
it should be set to true
. So in onPause
, if you are going out via getcounttask
,shouldNavigate
is going to be true
and if is true
, cancel your Timer else, start your Timer
.
Code:
public class AccountActivity extends AppCompatActivity {
private Timer timer;
private volatile boolean shouldNavigate = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
}
private class getaccounttask extends AsyncTask<String, Void, String>
{
@Override
protected String doInBackground(String... urlaccount)
{
StringBuilder result = new StringBuilder();
try
{
//My Codes
}
catch (Exception e)
{
e.printStackTrace();
}
return result.toString();
}
@Override
protected void onPostExecute(String result)
{
shouldNavigate = true;
Intent intent = new Intent();
intent.setClass(getApplicationContext(), AccountInformationActivity.class);
startActivity(intent);
}
}
@Override
protected void onPause() {
super.onPause();
if (!shouldNavigate){
timer = new Timer();
Log.i("Main", "Invoking logout timer");
LogOutTimerTask logoutTimeTask = new LogOutTimerTask();
timer.schedule(logoutTimeTask, 300000);
}else{
if (timer != null){
timer.cancel();
timer = null;
}
}
}
@Override
protected void onResume() {
super.onResume();
shouldNavigate = false;
if (timer != null) {
timer.cancel();
Log.i("Main", "cancel timer");
timer = null;
}
}
private class LogOutTimerTask extends TimerTask {
@Override
public void run() {
//redirect user to login screen
shouldNavigate = false;
Intent i = new Intent(AccountActivity.this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
}
}
Now a better approach could be keep a Service
and a Singleton
class.
The Singleton class would be
public Singleton{
private static Singleton instance = null;
private Singleton(){
activityMap = new HashMap<String, Activity>();
}
public static Singleton getInstance(){
if (instance == null) instance = new Singeton();
return instance;
}
public HashMap<String, Activity> activityMap;
}
Now each activity will have a Tag (like its name), so each activity when resumes will do
Singleton.getInstance().activityMap.put(tag, this);
and when goes to onPause
will do
Singleton.getInstance().activityMap.remove(tag, this);
So when the service finds that size of Singleton.getInstance().activityMap
is zero then clearly no activity is on foreground, so it starts a timer. when the timer expires check again if the count is still zero, if zero then perform your logout.