问题
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
- 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
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