I have an app that I use that automatically locks (requires a password entry screen)...
a) when the app starts for the first time
b) when another app is started and takes over the device
c) when the device "sleeps" automatically
d) when the user "sleeps" the device manually
(note: with c & d, if the user "awakens" the app within 5 seconds, it does NOT ask for the password)
I would like to do this for an app that I am writing as well so I created an activity (PasswordActivity
) with the necessary verification steps and have it working properly.
I originally placed it in the ONCREATE
of the MainActivity
(that was LAUNCHED in the AndroidManifest). That seemed to work fine. But then started on the re-lock capability. So tried moving it to the ONSTART
or ONRESUME
. But then when another ACTIVITY in my APP took focus, or the screen rotated, then the PasswordActivity
fired again. That won't work.
On here I found a thread recommending making it the LAUNCHER app in the Manifest and then when the password is OK, call the MainActivity. That seemed to work better... but then ran into an issue that it "re-locks" only when the user pressed the back button off the main screen (I assume stopping my app) and starts the app again. Doesn't catch another APP taking over the device although.
So based on that, and after looking at all documentation I can find on lifecycles (although most of those are ACTIVITY based, not APPLICATION based) not sure how to catch when the APP itself loses focus (another app takes over) and how to handle the automatic or manual sleep (C & D above) along with the time delay checking. I am assuming it is going to be a combination of several calls or steps, but not sure exactly which ones at this point.
Any recommendations?
I think I figured it out using some of the suggestions as well as some research. I am posting my solution here in case it can help someone else, someone sees a definite flaw I didn't see or encounter yet, or someone has some other input that may improved it.
As mentioned, the biggest problem as I can tell is there isn't any built-in function calls that can determine when "your app" is not in the foreground. The onPause
and onResume
are activity based, not app based... so changing from activity to activity in your app and even screen rotation, fires them.
To get around this... I created a global variable called gv.appPauseTime
. I created two separate universal utility functions I can call from anywhere in my app.
public static void lockAppStoreTime() {
gv.appPauseTime=new Date();
}
public static void lockAppCheck(Activity act) {
boolean bLock=false;
// Check to see if this is the first time through app
if (gv.appPauseTime==null) {
bLock = true;
} else {
Date currTime = new Date();
long diffMillis = currTime.getTime() - gv.appPauseTime.getTime();
long diffInSec = TimeUnit.MILLISECONDS.toSeconds(diffMillis);
// Lock app if 120 seconds (2 minutes) has lapsed
if (diffInSec > 120) {
bLock=true;
}
}
gv.appLastPause = new Date();
if (bLock) {
Intent j = new Intent(act, PasswordActivity.class);
act.startActivity(j);
}
}
In every activity, I create (or modified) the onPause
and onResume
like so...
@Override
public void onPause(){
super.onPause();
Util.lockAppStoreTime();
}
@Override
public void onResume(){
super.onResume();
Util.lockAppCheck(this);
}
When the onPause
fires, it stores the current date (time). When an onResume
fires in any function, it compares the current date (time) to the stored one. If 120 seconds (2 minutes) has lapsed, it displays the PasswordActivity to get the password verified. It does "store" the current date(time) before it calls the PasswordActivity so that it doesn't keep re-iterating it.
Basically, if there is a 2 minute gap, between an activity pausing and any activity, IN MY APP, resuming (or starting), it prompts for the password. If the user opens a different APP, and then returns to my APP... again, if it is at least a 2 minute lapse, then the password is asked for. If the user powers off or closes the app, then the restart will also trigger the password.
I chose 2 minutes, because that seems to be a decent "time lapse" in our app in general. Of course, that can be changed too.
So far, so good. Hope this helps anyone else.