I'm building an app which requires some security. Everytime user quit the application with the Home button, or when he locks the phone and unlocks it, a PIN code is prompted.
To add this feature, I need a callback fired when these situations happen. I tried to use onResume in my activities, but this method is also called while navigating between activities. I have also tried to implement an Application subclass, but there is no onResume override.
What is my best option?
It's not so trivial task to be honest. I've did it twice, and ended both times in:
- keeping state of app (locked, unlocked)
- using package manager to check if app is on top (==not set to background)
- calling functions that are checking for app locking onResume, onPause, onDestroy
- having timer that locks the app after some period of inactivity
My first implementation was based on activity with pin verification, second one - on fragments, and I'd suggest using fragments as
Related
Here's the situation:
I want to check if the device is rooted or not every time the app comes to foreground (either because they're launching the app through App Drawer or coming back to the app via Recent Apps list). This check is done during onResume(), and it's working well.
The problem is that the intention is to check for root only once when the app comes to foreground, not when user is currently using the app. Since onResume() is called when an Activity comes to foreground, this means the check is done multiple times even when it's not needed, which comes at performance cost.
I thought of using a static variable to lock it, locking just before I perform the check to ensure the check is only called once. This is fine and dandy, but the problem is when to do the unlock?
onPause() is called before another Activity comes to focus, which
would negate the lock. I tried to use isFinishing(), but if a user
presses the back button, the activity is destroyed, which resets the
root checking lock and renders it less desirable. EDIT: Also, the Activity is not finished if the user presses Home button, which means it's also not reliable enough
onStop() and onDestroy() are not guaranteed to be called, and
they're also called if the user presses back button.
Is there a way to call a function exactly once when the app moves to background, without restricted to the constraints of onPause() above? I searched through the Activity, Application, and BroadcastReceiver documentation but couldn't find any mention about such a thing
In the end, I decided to use a combination of onUserLeaveHint(), custom startActivity() and onBackPressed() to do it, with some private static and non-static variables
I used onUserLeaveHint() to detect when user is going back to Home
or to Recent apps list.
onBackPressed() is used to tell the app that it is used for
navigation, while another onBackPressed() override is written at the
app entry point to detect when user is using back button to go back
to Home (can't believe onUserLeaveHint() doesn't account for that)
the custom startActivity() makes sure that onUserLeaveHint() is not
called when another activity is started. While onUserLeaveHint() has issues with forced interruptions (such as user receiving a call), it is deemed acceptable for now.
I did some research and found this blog but it makes use of onStop(), which is not guaranteed to run
Thanks for all the responses. I understand the concern about my security approach, but the question is about detecting when the user is leaving the app
I want to be notified when my Android App comes back to focus or is started. The tricky part is, i don't care for the events which appear when switching Activities within the App. The Events i am interested in are:
App is started
App is reactivated on any Activity (brought back to front by the user)
I tried handling it with the onStart() and onResume() Methods, but they fire every time a Activity is loaded and call onStop even when they just switch Activities within the app
I checked the lifecycle (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle) but even the onDestroy() is called when solely switching Activities within the App.
How can i determine if my App is reactivated or just switching Activities?
you have to override Application class for **App is started** this will call once every time when app is open.
Two possible solutions come to mind, neither of them is very clean.
1) Use a timer
Every time in your onPause() method, you schedule a timer that sets a flag after 1 Second (or something longer, depends on your exact use-case). In each onResume() you check if the flag has been set, e.g. your App has been inactive for longer than the timer interval. If the flag is set you know the user did something else between the onPause() and onResume()
2) Set a flag manually
Every time you trigger a switch between Activities in your App, you set a flag somewhere in your application. In your onResume() method, you check if the flag is set, e.g. the switch was triggered by your App. If it is not set, the user comes from outside of your App.
Both methods, however, can't discriminate any further between possible use-cases. All these cases will look the same to you:
the user presses the home button and resumes the app at any given time later
the user turns the screen off, and back on again
the user gets a phone call and then immediatly returns to your app
This might lead to undesired behaviour of your App. I don't know what exactly you want to use this mechanism for, but you have to think very hard about all the possible cases, and if you want them to trigger your behaviour, or not.
In Windows Phone, there is Application.LoadCompleted Event for detecting the finish of starting an application.
Note the finish means that users are able to interact with the app.
Is there similar API on Android? Any other approaches to achieve this?
after onResume() gets called it means the user can start interacting with your app. Consult this document for more information
You can override onCreate method of main Activity.
It depends what you mean by 'finished starting'. Activities, including the main activity, can be created and destroyed - and therefore onCreate() called - multiple times, for example (in the default behaviour) when the device orientation changes. onResume will be called even more often, for example every time the activity comes to the foreground. Then there's onStart(). See the Android developer docs to see when in the lifecycle each is invoked. It's true that the first time onResume() is called on the main activity will be when the app is fully started, but you won't know it's the first time without storing state somewhere outside any activity, for example on a singleton, or by subclassing the Application class, which is not something especially encouraged, as far as I can tell.
I am trying to achieve the following with Android :
when the app is in background, a thread polls a server every now and then to retrieve data and notifies the user if new data is available. I am using a Service for that, fine.
when the app is in "active" use, i.e. one of its activities is visible, the polling should stop as it might interfere with other user actions.
I don't understand how to detect the transition between the "active" or "background" use of the app. The onResume() activity methods does not seem to help, as an activity can be hidden or visible during "active" use anyway. My understanding is that the app itself doesn't make the difference between the 2 states.
Can it be related when the HOME button is pressed ? Is there another way to do the distinction ?
I am thinking of an equivalent of iPhone's app delegate method applicationDidEnterBackground. Is it the right way to think with Android ? Or shall I use another approach ?
Thank you.
I'm going to reference the Activity Lifecycle. In between onResume and onPause your Activity is 'active', i.e., it's on the screen and the user can interact with it. If your activity's onPause method is called then you should assume that it is no longer 'active' and the user cannot interact with it anymore until onResume is called again. If you wish to track this in your service you're going to have to do this manually.
This is probably most easily achieved by calling a method in your service in Activity#onResume that increments a counter or sets a flag and in onPause reverting that change. If you have multiple activities then you're most likely going to need a counter, probably an AtomicInteger, and use it to determine when you should resume your polling.
I would probably wait for a small bit of time when the counter reaches 0, recheck it, and if it is still 0 resume polling. This would account for the gap between one activity's onPause and another's onResume.
Like the title says, I need to detect when my app loses focus because another app is launched (Phone call comes in, or user hits Home etc).
Overriding Activity.OnStop does not work because that is called even when switching activities within my app.
I believe you could use:
onWindowsFocusChanged(boolean hasFocus)
from your Activity.
AFAIK Android offers no facility for this. You may be able to track this yourself (e.g., if onStop() in one of your activities is called, and onStart() in another of your activities is not called within X period of time, presumably some other app's activity is in the foreground).
With ICS upwards this may be possible.
This is taken from the android site:
To be notified when the user exits your UI, implement the
onTrimMemory() callback in your Activity classes. You should use
this method to listen for the TRIM_MEMORY_UI_HIDDEN level, which
indicates your UI is now hidden from view and you should free
resources that only your UI uses.
Notice that your app receives the onTrimMemory() callback with
TRIM_MEMORY_UI_HIDDEN only when all the UI components of your app
process become hidden from the user.
See this page for full details http://developer.android.com/training/articles/memory.html