计时器不会停止在旧活动

时间:2016-08-24 04:17:05

标签: android android-timer

我在AccountActivity.class设置了一个计时器,以确保用户不按下主页按钮,否则将开始倒计时以退出用户或用户锁定他的屏幕。

但是由于onPause方法,我现在面临一个问题。当我的用户点击调用getaccounttask()方法的按钮并将其用户重定向到AccountInformationActivity.class时,onPause方法也会被激活并且计时器开始倒计时。

是否有任何解决方案可以阻止onPause方法倒计时或在AccountInformationActivity.class上取消定时器?

我尝试在我的意图开始之前取消计时器,但仍然无效。

我也尝试过使用处理程序,但遇到了同样的问题,我仍在努力掌握Android的完整工作方式,所以非常感谢您的帮助或解决方案。

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();
        }
    }
}

2 个答案:

答案 0 :(得分:0)

嗯,您选择的实施架构可以改进。我稍后会谈到这个。首先应用此快速修复程序来修复您的体系结构。

显然,当您使用主屏幕离开Timer时,您想要启动Activity。但是,使用Activity切换为Intent,用户也可以退出AccountActivity。这可以跟踪。所以保留一个像shouldNavigate这样的布尔标志,最初它应该是false。在onResume时,应将其设置为false,但当getcounttask转到onPostExecute时,应将其设置为true。因此,在onPause中,如果您通过getcounttask出去,shouldNavigate将是true,如果是true,请取消您的其他计时器,启动您的Timer

代码:

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();
        }
    }
}

现在更好的方法是保留ServiceSingleton类。 Singleton类将是

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;

}

现在每个活动都有一个标签(就像它的名字一样),所以恢复时的每个活动都会有

Singleton.getInstance().activityMap.put(tag, this);

当转到onPause时会做

Singleton.getInstance().activityMap.remove(tag, this);

因此,当服务发现Singleton.getInstance().activityMap的大小为零时,前景中显然没有活动,因此它启动了一个计时器。当计时器到期时再次检查计数是否仍为零,如果为零,则执行注销。

答案 1 :(得分:0)

onPause()中进行一些修改并添加此权限

<uses-permission android:name="android.permission.GET_TASKS" />

    @Override
    protected void onPause() {
        if (isApplicationSentToBackground(this)) {
            // Do what you want to do on detecting Home Key being Pressed
            timer = new Timer();
            Log.i("Main", "Invoking logout timer");
            LogOutTimerTask logoutTimeTask = new LogOutTimerTask();
            timer.schedule(logoutTimeTask, 300000); //auto logout in 5 minutes
            Log.i("Main", "Invoking Home Key pressed");
        }
        super.onPause();

    }

    public boolean isApplicationSentToBackground(final Context context) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
        if (!tasks.isEmpty()) {
            ComponentName topActivity = tasks.get(0).topActivity;
            if (!topActivity.getPackageName().equals(context.getPackageName())) {
                return true;
            }
        }
        return false;
    }