Detect if an app is started/resumed from 'outside' the app

本秂侑毒 提交于 2019-12-01 04:22:01

问题


I'm currently concepting a feature for an app, where I'd like a general method/approach to detect if the app itself was started or resumed from 'outside' the app.

'Outside', in this case, means:

  • app was started/resumed by the launcher icon
  • app was started/resumed by pressing the 'app button' from a navigation bar/key (like on a nexus 7)
  • app was started/resumed from a notification
  • app was started/resumed from 'somewhere else'

The use case for this feature is the following:

  • The app has a 'multi-user-ability' that allows the user(s) to create one ore more profiles for his/her data
  • A single profile may be pin/password protected to 'hide' the data from other user(s) of the app, or 'hide' data from other user(s) of the device where the app is installed
    • If a profile has a password set, the app will show some kind of a lock screen to the current user when the app is started/resumed
      • If entered correctly, the app will start normally showing the data of the last select profile
      • If entered incorrectly, the app will start with a 'neutral' profile or no profile at all

I've searched the web for ideas, and found relevant posts on stackoverflow only:

  • Is there any way to distinguish between an Android Activity onResume from the home screen?
  • Android - detecting application launch from home or history
  • Determine if app was launched from home screen?

From what I've read and learned so far is, that a solution seems to be more complex than I've thought and that there's no out of the box solution for this.

I'm currently thinking about a time-flag based approach to implement this feature:

  • set a time flag as a member variable of an affected activity
  • onCreate(Bundle savedInstanceState) --> flag is set to 'null' before checking the savedInstanceState Budle for data
    • this detects an activity start --> if password is set --> show the lock screen
  • onSaveInstanceState(Bundle) --> set time flag to the 'current time'
  • if onCreate(Bundle savedInstanceState) is resumed, savedInstanceState will contain a time flag
    • calculate a diff between the current time and the time the app was paused last
    • if this diff is above a certain threshold , e.g. 30 minutes --> and if the password is set --> show the lock screen

Maybe some of you have already implemented something similiar or do have some input to this matter/approach. I'd be glad to hear your ideas.

Cheers


回答1:


It's an older question but still relevant. There is a simple solution using ActivityLifeCycleCallbacks. This answer is derived from this blogpost by Micahel Bradshaw. He explains the concept

The key is in understanding how activities coordinate with each other. When switching between activities A and B, their methods are called in this order:

A.onPause();

B.onCreate();

B.onStart();

B.onResume(); (Activity B now has user focus)

A.onStop(); (if Activity A is no longer visible on screen)

Solution: You create a class which implements Application.ActivityLifecycleCallbacks interface and keep count of resumed and stopped activities.

public class AppLifecycleHelper implements Application.ActivityLifecycleCallbacks {

// I use two separate variables here. You can, of course, just use one and
// increment/decrement it instead of using two and incrementing both.
private static int resumed;
private static int stopped;

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        ++resumed;
    }

    public void onActivityPaused(Activity activity) {
    }

    public void onActivitySaveInstanceState(Activity activity, Bundle     outState) {
    }

    public void onActivityStarted(Activity activity) {
        if (!isApplicationInForeground()){
            // resumed and stopped both are 0,
            // that means it is the first activity to come on display
            // i.e. App is launched from outside the app
        }
    }

    public void onActivityStopped(Activity activity) {
        ++stopped;
        if (!isApplicationInForeground()){
            // resumed and stopped both are 0
            // That means there is NO Activity in resumed state when this activity stopped
            // i.e. User came out of the App, perform all Application wide persistence tasks over here
        }
    }

    /**
     * Checks whether App is visible to the user or not
     * @return true if visible and false otherwise
     */
    public static boolean isApplicationInForeground() {
        return resumed > stopped;
    }

}

And then in your Application's onCreate() register this class for Activity callbacks like this

registerActivityLifecycleCallbacks(new AppLifecycleHelper());

and that's it! No need to add any code to every activity. Everything is contained in AppLifecycleHelper with just a few lines of code.



来源:https://stackoverflow.com/questions/20126231/detect-if-an-app-is-started-resumed-from-outside-the-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!