Search code examples
androidtimeout

How to control activity flow within Android in timeout situation?


I have a small android app that consists of 1 main activity (started activity, anyone can use) and some 3 more activities that require a login with a password.

I have created an application class that holds the info whether someone is logged in or not.

In addition the user shall be logged out and sent automatically to the main activity after 5 minutes of inactivity. For this purpose I created a thread within the application class that sleeps 5 minutes and then logs out the user and brings up the main activity.

Here the relevant code:

public void setLoggedOut() {
        isLoggedIn = false;
        if (mTimerThread != null) {
            mTimerThread.interrupt();
        }
        Intent myIntent = new Intent(MyApplication.this.getBaseContext(), MainActivity.class);
        myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(myIntent);
    }

startActivity above works on some devices (tablets), on others I get the following error and the app crashes:

android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Of course I do not want a new task, but just finish all the other activities and go back to the main one (FLAG_ACTIVITY_CLEAR_TOP sounds to be the right one). There are already threads with this error here in stackoverflow, but nothing that helps to solve my problem.

As mentioned on some devices (even emulated in Android studio) it works as it should, on some it doesn't . Could be that it is a question of the API level (API 25/Android 7.1.1 worked, API 22/Android 5.1 did not), but I am not sure...

I could (probably) implement the timeout mechanism in each activity separately but that looks to me not the best solution, I hate to duplicate code when not required.

Any ideas? Alternative/better concepts?


Solution

  • Any ideas? Alternative concepts?

    Keep current activity context and start new activity from it:

    public class App extends Application {
    
        ....
    
        private WeakReference<Activity> currentActivityRef = null;
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            ...
    
            registerActivityLifecycleCallbacks(
                    new ActivityLifecycleCallbacks() {
                        @Override
                        public void onActivityCreated(Activity activity,
                                                      Bundle savedInstanceState) {
                            currentActivityRef = new WeakReference<>(activity);
                        }
    
                        @Override
                        public void onActivityStarted(Activity activity) {
                            currentActivityRef = new WeakReference<>(activity);
                        }
    
                        @Override
                        public void onActivityResumed(Activity activity) {
                            currentActivityRef = new WeakReference<>(activity);
                        }
    
                        @Override
                        public void onActivityPaused(Activity activity) {
                        }
    
                        @Override
                        public void onActivityStopped(Activity activity) {
                        }
    
                        @Override
                        public void onActivitySaveInstanceState(Activity activity,
                                                                Bundle outState) {
                        }
    
                        @Override
                        public void onActivityDestroyed(Activity activity) {
                        }
                    }
            );
        }
    
        ...
    
        public void setLoggedOut() {
            isLoggedIn = false;
            if (mTimerThread != null) {
                mTimerThread.interrupt();
            }
    
            if (currentActivityRef != null) {
                final Activity activity = currentActivityRef.get();
                if (activity != null && !(activity instanceof MainActivity)) {
                    activity.startActivity(new Intent(activity, MainActivity.class)
                            .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
                }
            }
        }
    }