My android application has multiple Activities. I need to perform a few things when the Application resumes (Application not Activity).
Android application provides onCreate callback but no onResume callback.
Is there any way I can identify that my application has resumed?
Applications do not get paused or resumed, only individual activities do. You can think of the Application class as of a static object that gets created before any of your activities (that's why it has a onCreate() function) and gets destroyed when the system kills the process (no onDestroy() involved here).
I believe the only way you can do that is through the Activity. If you're looking to call something across all your Activities in the onResume you can probably use a static singleton as is suggested in the Application docs:
There is normally no need to subclass
Application. In most situation, static
singletons can provide the same
functionality in a more modular way.
If your singleton needs a global
context (for example to register
broadcast receivers), the function to
retrieve it can be given a Context
which internally uses
Context.getApplicationContext() when
first constructing the singleton.
Activities do have onResume() see here: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
#Override
protected void onResume() {
// ...
}
So when your application resumes - one of your activities will resume - handle it in each activity.
Use ProcessLifecycleOwner ProcessLifecycleOwner .
It will dispatch Lifecycle.Event.ON_START, Lifecycle.Event.ON_RESUME events, as a first activity moves through these events.
And Lifecycle.Event.ON_PAUSE, Lifecycle.Event.ON_STOP, events will be dispatched with a delay after a last activity passed through them
Related
I have an application with multiple activities and have some behavior in onPause on my MainActivity that I don't want to happen when switching to another activity.
Right now whenever I switch activities the MainActivity onPause() is called and it always runs the behavior.
Activity lifecycles are tightly coordinated, so when launching one Activity B, from Activity A, the following lifecycle events will take place: ActivityA.onPause, ActivityB.onCreate, ActivityB.onStart, ActivityB.onResume, ActivityA.onStop. You can definitely leverage this lifecycle coordination to achieve what you want, if you are move you "behavoir" to the lifecycle method onStop (which is a better place to do most shutdown/stopping work at).
Create a Lifecycle registrar object that will perform the "behavior" when there are no activities are registered in the Lifecycle registrar object. Register your Activities inside of their onStart() and onStop() liefycle callbacks. Inside of the deregister method of your Lifecycle registration object check to see if there are any registered objects and if their aren't you perform you "behavior" whatever that may be. You can extend this functionality to work with Services, just register and deregister the service with the Lifecycle registrar inside the Service's onCreate, onDestroy respectively.
Using onStop instead of onPause, has the added benefit of keeping you from doing your paused/stopped "behavior" when the app is actually in the background and not just partially visibly, such as the case when the system displays a dialog. For example, when requesting to start Bluetooth, the Android OS will generate a dialog prompting the user, and calling onPause. This makes since for some apps but not all apps, and when you think about it, there are a various other use-cases that will cause the app to enter onPause(), that would be annoying to the user for you app to perform shutdown processes.
I have personally utilized this scheme to maintain a open connection, while the app is open and close the connection when the app is killed, or placed in the background. I even modified the Lifecycle Registrar object to maintain the connection during device rotation.
Here's a solution (a little dirty), you can use a boolean to know when you're switching the activity, set it to true just before you call startActivity(intent), and set it to false in onResume().
P.S, using onStop() is better than onPause() in your case, i believe you don't want to delete those cookies when the activity is partially visible
We have Splash extends Activity which is the starting activity of our application. We also have CustomApplication extends Application class which is invoked when the app process in invoked.
Now we have the following requirement. Whenever the app/process is launched, call Utils.doSomeDBWork() function.
For this purpose we have put this function call in onCreate() of Splash and CustomApplication classes. The reason that we have put this call inside CustomApplication is that our application can be launched via deeplinks/notifications in which Splash won't be called. But the problem is that if the app was killed and launched via Splash, then the same function will be called twice. One from CustomApplication and the other through Splash.
So basically my question is that if the function has already been called from CustomApplication, then don't call this function from Splash. I can think of doing it by using some static variable or Shared Preferences. But don't think that this is a clean way. Is there any other way to achieve this, like passing some info through Intents etc?
How to know that Application class was called before Activity launch?
In brief, every time when Android "gets a request" to start any of your app component (Activity, Service, BroadcastReceiver) and your app isn't running yet, it forks the app_process (a.k.a zygote), changes its name to your.package.name defined in AndroidManifest.xml, initializes an Application instance, calls its onCreate() method, then instantiates the component requested and calls its lifecycle methods (Activity's onCreate(), Service's onCreate() or BroadcastReceiver's onReceive()).
For this purpose we have put this function call in onCreate() of splash and CustomApplication classes.
It's redundant. It's enough to call it only from Application's onCreate() which is the earliest "entry point" to an app that is guaranteed to be called before any other component's lifecycle methods. There can be only single instance of Application class which lives untill the app process dies.
You can easily test it by logging each of the lifecycle methods. After that you won't have any doubts left.
EDIT w.r.t the OP's comment:
If the app process was running and the user back presses and exits, and then launches the app again, then CustomApplication class won't be called.
This is only partially true. CustomApplication's onCreate() won't be called unless the system kills the app process while it is in background (simulate the case by, for example, swiping your app from Recents).
But our requirement is that CustomApplication class should be invoked in this case.
It's out of developer's scope. Only the system controls that.
That being said, CustomApplication's onCreate() will be called if Android kills the app in background. If it doesn't, a simple way to achieve the requirement is to have a boolean flag in CustomApplication which would indicate if Utils.doSomeDBWork() was called.
Why don't you call from only applcation's class onCreate?
when App is launched from deeplinks/notifications or Splash, Applcation will always be created first.
Also you can check from static variable.
like below.
class Utils{
public static boolean doneWork = false; // this static variable will be false when app process is killed.
public doSomeDBWork(){
if(!doneWork){
//alreay done..
return;
}
:
:
doneWork = true;
}
}
You could do some controls with ActivityLifeCycleCallbacks on application layer. If using it in splashActivity is a solution for you,track your activities and make call in your callback. I hope it gives an idea.
How can I stop my whole App in simple terms? (all activities, services, Threads, etc. simply everything) The life-cycle callbacks (especially onStop() and onDestroy()) should be called.
Google suggests the following possible solution:
kill the process: but this wouldn't call the lifecycle callbacks
and finish(); but this is only for one Activity:
But is it possible to access this method from outside like:
//Getting all activityies, how?
//For each gotten activity
AcitvityName.finish();
or via or via getParent().finish(); ?
This did not help me: Best way to quit android app?
FD
#Override
public void onPause() {
if(isFinishing()){
//code to finish() all activitys threads etc.....
}
super.onPause();
}
in onPause() you can check for isFinishing() and then if it is finishing it goes to onDestroy() so you can execute some code youd like
Use a broadcast receiver to call all your activities and call finish locally in them, invoking the current lifecycle callbacks.
Broadcastreceiver and Paused activity
http://developer.android.com/reference/android/content/BroadcastReceiver.html
Android don't allows user close application directly. You may minimize it to background or directly killing process.
But if you want to call some callbacks and release any resources when user remove your application from screen - you may to do following:
Clearing activity stack in onDestroy method (or if you wish in onBackPressed, onHomePressed). It must calls onDestroy methods in all removing activities so you may release any extended resources in onDestroy method of activity which has links on it.
So when user exit from your application - it will remove his activities and release all resources.
According to the android Activity Lifecycle, the only callback guaranteed to be called (if an activity ever leaves the Running state, which is typically expected) is onPause().
So, I must assume that there are scenarios in which it makes sense to implement onStop() and onDestroy() although they are not really guaranteed to be called.
I understand that onStop() should be implemented when it's possible for an activity to return to the Running state via the Stopped state (why would it do that instead of returning directly is a different question).
But the need for onDestroy(), when I can place all cleanup/state-saving into onPause(), is unclear to me.
Can you describe a real-app situation (i.e. not analogy to driving a car etc.) in which it would make sense to implement onDestroy()?
onDestroy will be called if you explicitly call finish(); yourself.
Your main activity calls startActivityForResult on a map activity.
Map activity with a LocationListener, the user clicks the map and selects say a local restaurant.
The activity then , sets up some extras to be sent back to your main activity, it then explicitly call's finish(); on itself and in the onDestroy kills the LocationListener and other variables you had invoked.
Just found this in the docs
onDestroy() = The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
Can you describe a real-app situation
(i.e. not analogy to driving a car
etc.) in which it would make sense to
implement onDestroy()?
When you want to capture a configuration change. It's all in the SDK:
http://developer.android.com/reference/android/app/Activity.html
I have a Service which tracks the location of the user. Currently, the Service boots when the application starts and stops when the application terminates. Unfortunately, if users keep the application in the background, the Service never stops and drains battery.
I would like the Service to stop when my application is not in the foreground. I was hoping the Application class would let me Override onPause and onResume handlers, but it does not have them. Is there another way I can accomplish this?
I haven't tested this yet, but it looks like if you use Context#bindService() (instead of Context#startService()), the service should stop when no more activities are bound to it. (see Service lifecycle).
Then use onPause()/onResume() in each activity to bind/unbind from the service.
Alternatively, you could add a pair of methods on your service which tell it to start/stop listening for location updates and call it from each activity's onResume()/onPause(). The service would still be running, but the location updates wouldn't be draining the battery.
Reading all the above answers I would suggest Simply add a boolean global flag for each activity & put it in your onResume & onPause & also while launching an Activity Something like this
public void onPause()
{
super.onPause();
activity1IsResumed = true;
}
&same for onResume
& similarly when launching a new Activity
startActivityForResult(myintent ,0);
activity2IsResumed = true;
activity1IsResumed = false;
then in your Service simply check
if(activity1IsResumed || activity2IsResumed || activity3IsResumed)
{
//your logic
}
else
{
//another logic
//or dont run location tracker
}
& you are done!
You should override the onPause and onResume methods on your Activity. If you have multiple activities you may want to have a common base class for them and put the start/stop logic into the base class.
I have not tried this approach but I think you can override the home key of android device by using KeyEvent.KEYCODE_HOME and you can use stopService(Intent) to stop your service and when again application resumes, you can write startService(Intent) in the onResume() method of your Activity.
This way I think your service will only stop when user explicitly presses home button to take application in the background and not when he switches from one activity to another.
What I would suggest is overriding the onPause/onReume methods as others have said. Without knowing more about the flow of your application and interactions between Activities, I can't give much more information beyond guesswork.
If your Activities are persistent, however, my recommendation would be to utilize the Intents better when switching between Activities.
For instance, each Activity should have a boolean "transition" flag. So, when you move from one Activity to the next, you set up an Intent extra:
intent.putExtra("transition",true);
Followed in the receiving Activity by: (in onCreate)
intent.getBooleanExtra("transition",false);
This way, for each Activity that launches, you can know whether it has come from another Activity, or if it has been launched from a home screen launcher. Thus, if it gets a true transition, then onPause should NOT stop the service--that means you will be returning to the previous Activity after it returns. If it receives no "transition" extra, or a false transition, then you can safely assume there is no Activity underneath it waiting to take over for the current one.
On the first Activity, you will simply need to stop the service if you are switching to another Activity, which you should be able to figure out programmatically if one Activity is started from another.
It sounds like the real problem is how to only stop the service when you go to an activity that isn't one of your own? One way would be to in your onPause method to stop the activity. Do this for all your activities. Then override your startActivity method. And in here do a conditional test to confirm that you are purposefully navigating to one of your own. If your are set a flag to true.
Now go back to your on pause overridden method. And only stop your service if the flag is not equal to true. Set the flag to false.
All events that navigate away will close your service. Navigating to your own will leave it intact.
Do the overriding in a base class that all your activities extend.
Writeen in my andolroid. Will post ezaple later.
Try using the Bound Services technique to accomplish this.
Bound Services | Android Developers
You can use bound services in a way such that the service will stop when no activities are bound to it. This way, when the app is not in the foreground, the service will not be running. When the user brings the app back to the foreground, the Activity will bind to the service and the service will resume.
Create methods registerActivity() and unRegisterActivity() in your Application object and implement first method in all you acts onResume() and second in acts onPause().
First method add activity to List<Activity> instance in your app object, unRegisterActivity() checks size of list in every call if==0 stopService();.