I'm working on my 1st Android app and wondering how to handle activation/deactivation/starting/stopping globally, not on Activity level.
This great article shows states transition for Activities:
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Is there something similar for Application states?
For example at iOS and Windows Phone app there is clear app states separated from activities (views, controllers, whatever).
I'm asking because I want to perform certain operations only once per app loading/exiting not with every activity starting/stopping
The answer is There is Simply No Direct method to do this
rather than in Application Class you can catch these events
#Override
public void onLowMemory()
{
super.onLowMemory();
}
#Override
public void onTerminate()
{
super.onTerminate();
}
So you will have to handle it in all the Activities you will be having
the following methods
onResume()
onStart()
onRestart()
onPause()
onDestroy()
You will have to implement in all Activity to handle for all application
A suggesstion
You can have some Variable in Application class to save application state
say create a variable like
public static boolean isPaused;
and set it from all activity on state change
The question you're asking is applicable for iOS and Windows but not really for Android.
Android doesn't really have a concept of an application as an object, although there's an Application class. Instead, an app is a loose collection of Activities. There are many good reasons for this state of affairs; for example, it supports fast app switching and easy interaction between Activities of different apps.
The best way to coordinate your "app" so that one Activity doesn't try to do something that's already been done is to use SharedPreferences to store app state. Nearly every other way of doing it is less preferred. Even if the system kills off your entire app, SharedPreferences will maintain the current state. The Application object won't.
Also, Android is based on pausing and resuming. An Activity or activities are created, pause, and resume. They may be destroyed, but that's an extreme case. A corollary to this is that apps should not have an exit button; there's no need for one. I sometimes see apps that have one, but what they're really trying to do is shut down a background Service or process. The best way to do that is to have an affordance that says "Sleep" or similar.
Have all activities inherit from the same hierarchy and put whatever you want in OnCreate, OnPause, OnResume, OnStop, OnDestroy and call the super where applicable.
Example
Parent
IamTheParentActivity : Activity
protected void onCreate()
{
setApplicationState(ApplicationState.Running);
}
protected void onPause()
{
setApplicationState(ApplicationState.Paused);
}
private void setApplicationState(Enum ApplicationState)
{
//Some Application Level Variable
Application.State = ApplicationState
}
Children
IamTheChild : IamTheParentActivity
protected void override onCreate()
{
base.OnCreate;
do other stuff
}
Related
I want to perform logic whenever my Android app is in the process of being closed, so to avoid duplicating the same logic on each Activity.
Similar to OnCreate() below, which is invoked whenever the app is starting, I need the close/terminate method.
public class Application : Android.App.Application
{
public override void OnCreate()
{
}
}
Most of the times your Application class will not know that it is going to shut down because usually it is just killed by the system. You can hide activity but you can't hide application since it is always there (as long as process runs). And if user (or system) decides to manually kill it you will not get any chance to save your data since it might be time consuming. So the best way would be to call custom method in Application from your Activity's onStop() and save everything you need. And it will be a good idea to save data in background thread.
In activity class:
#Override
protected void onStop()
{
((CustomApplication)getApplication()).onCloseCustom();
super.onStop();
}
In your application class
public void onCloseCustom()
{
//do whatever you need
}
When I write my activities on android, I have to override a lot of "lifecycle" methods, such as onCreate, onActivityResult:
class MyAcitivity extends Activity {
#Override
public void onCreate(...) {}
#Override
public void onStart(...) {}
#Override
public void onActivityResult(...) {}
#Overide
public void onBackPressed(...) {}
}
I don't like this, because I found my logical code are split to everywhere in my class. I do some operation in this method, but I have to handle the result in another method.
Is it the only way to design Activity like this? Is there any other solution can let me do the same without overriding methods from super classes?
Update
I do some operation in this method, but I have to handle the result in another method.
For example:
public void onCreate(...) {
startActivityForResult(new Intent(this, AnotherAcitity.class), INTENT_ANOTHER);
}
public void onActivityResult(...) {
if(requestCode == INTENT_ANOTHER) {
// do something
}
}
Update again
I know how to use these lifecycle methods, what I'm thinking is the "design". Is there any different way to design android (in theory) without "overriding lifecycle methods" to write activities. Does ios and win8 on mobiles use the same design as android? If I develop an ios or win8 application, do I have to override all kinds of lifecycle methods as I do on android?
You only need to override the methods you're using in your Activity. So if your activity simple displays a help page that has already been populated in the XML, you only have to override onCreate() and call setContentView().
In general, if your overriden method is like:
public void myOverridenMethod() {
super.myOverridenMethod();
}
That is to say, it contains nothing but a super call, you need not override it.
In the example you provided, you must override the appropriate lifecycle methods as the calling of these is beyond your control, unless you're willing to develop a custom ROM for your device(s).
EDIT
The Android lifecycle methods are called by the system at specific predefined points in your app's life.
You cannot design an Activity in a different way, as if you do Android has no idea which method does what. However, it knows exactly when to call which method in the Android lifecycle. By using your own methods instead of these, you have an app which Android cannot interact with.
Additionally, many lifecycle methods like onCreate() etc. help setup the initial bits of your app (like getting it a Context).
iOS and Windows Phone and BlackBerry have similar lifecycle methods, but they don't always have an exact Android equivalent, as all are different platforms and handle their apps differently.
This is just a generic framework pattern, framework doesn't depend on you, just notifies you, all your actions are optional for framework. It's called Inversion of Control.
This is just opposite to the direct style of programming where you decide everything about the Application, and give commands to framework.
Google developers designed Activity class, and Android only works through them. Android calls these methods whenever it pleases. Android does not care what you do in those methods, it just cares to notify you of the life cycle events.
Since everything is optional, you just have to fill in the places you are really interested in. An empty Activity runs just fine.
public class MyActivity extends Activity { }
If anything additional needs to be done, just add the code at correct place:
public class MyActivity extends Activity {
#Override
public void onCreate(...) {
//---whatever you want to do in this stage of life cycle----
}
}
You dont necessarily need to override all methods of life cycle of an activty. They all are for a specified purpose
onCreate() :
Called when the activity is first created. This is where you should do
all of your normal static set up: create views, bind data to lists,
etc. This method also provides you with a Bundle containing the
activity's previously frozen state, if there was one. Always followed
by onStart().
onRestart() :
Called after your activity has been stopped, prior to it being started
again. Always followed by onStart()
onStart() :
Called when the activity is becoming visible to the user. Followed by
onResume() if the activity comes to the foreground, or onStop() if it
becomes hidden.
onResume() :
Called when the activity will start interacting with the user. At this
point your activity is at the top of the activity stack, with user
input going to it. Always followed by onPause().
onPause ():
Called as part of the activity lifecycle when an activity is going
into the background,
but has not (yet) been killed. The counterpart to onResume().
When activity B is launched in front of activity A, this callback will be invoked on A.
B will not be created until A's onPause() returns, so be sure to not
do anything lengthy here.
onStop():
Called when you are no longer visible to the user. You will next
receive either onRestart(), onDestroy(), or nothing, depending on
later user activity.
Note that this method may never be called, in low memory situations
where the system does not have enough memory to keep your activity's
process running after its onPause() method is called.
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.
I.e I would like to know when user interact with my application and when not.
I have tried do it using ActivityManager.getRecentTasks(). I have checked root activity at a top task to detect interact user with my application or not.
I have forced to check it in separated thread each second or two.
This way is bad for me. There is another way to detect when any activity of my app are opening or closed?
Have a look at the lifecycle of an Activity.
There are callback methods (onStart, onResume, onPause, onDestroy, ...) that are invoked by the system whenever your activity is created, becomes active or inactive etc.
You might create your own application class (just inherit from android.app.Application) and do your tracking there. The application will be around as long as your app is running.
For example you could put a flag or a counter there and set it from the activities' callbacks. A simple example for that could be:
public void onResume() {
super.onResume();
((MyApplication)getApplication()).active = true;
}
public void onDestroy() {
super.onDestroy();
((MyApplication)getApplication()).destroyed += 1;
}
I have a complex Android app with a decent amount of application state that needs to be persisted (in a specific format). Writing out the data is not an instantaneous operation and so it would be ideal to minimize persisting it unnecessarily.
Because of the persistence overhead it is not practical to persist the state every time it is changed. Ideally, persisting state would be triggered when the app is "backgrounded" by the user tapping the 'home' button or tapping the 'back' button on the app's root Activity (or by an incoming call, etc.). This minimizes persistence overhead while maintaining state consistency from the user's perspective. The question is how can you detect if the app is being "backgrounded"?
The Activity lifecycle calls (onStart, onResume, onPause and friends) don't help as the app has many different activities, any one of which could be active when the user taps 'home'. Furthermore, the calls get called when Activities get pushed, popped (and bottom killed) on the Activity stack and so they don't reflect if the app is going away or not.
So how does an app detect when it is going to the background?
If you want to persist some state when any of your activities goes to the background you could always extend Activity, add two abstact methods which you call in onPause and onResume. Then each one of your Activities which extends this new abstract class would be forced to define saveState() and loadState(). These methods could define what to save and load for each activity.
That is just an example of using inheritance to force your programmers to implement otherwise overlooked methods and techniques methods. You can just tell your programmers, if you ever need to save the state of an activity just extend this type of activity and then the IDE will put them on the path of your design.
package com.yourcompany.yourpackage;
import android.app.Activity;
public abstract class ActivitySaveState extends Activity{
#Override
protected void onPause() {
super.onPause();
saveState();
}
#Override
protected void onResume() {
super.onResume();
loadState();
}
public abstract void loadState();
public abstract void saveState();
}
Also you could instantiate some of the state saving mechanisms for them in the super class (i.e. web service endpoint, DAO or w/e your persistence unit maybe.
#Override
protected void onResume() {
super.onResume();
saveState();
CustomDataAccessObject dao = new CustomDataAccessObject("Activity3");
loadState(dao );
}
public abstract void loadState(CustomDataAccessObject dao);
As far as I got in Android there is no concept of application going to background as a whole. Your application is thought of in terms of a federation of activities/services/... working together. And potentially you could configure it so that it can start from different activities, in different processes, in different tasks, so it's (almost?) impossible to figure out when your application goes to background.
Apart from this, to your question:
MyXxxActivity.onPause is the last safe chance you have to trigger the saving of data that has to be persisted across different "runs" of your application. This is not transient application state, instead it's stuff that goes to DB/File System storage and that you want to retrieve again in the next run.
I assume the application state you mention falls into this category.
So your saving must be triggered from each activity's onPause. If there's any state shared across different activities (e.g. in the Application), it should be collected from each onPause. Or its saving should be triggered as well from each onPause.
If the saving operation takes time, you should not run it on the main (UI) thread. Instead you should hand it off to another thread. Again, assuming this is important state that you do want to be persisted, then it's best to hand this work to a Service (as opposed to an AsyncTask e.g.).
The Activity lifecycle calls (onStart, onResume, onPause and friends) don't help as the app has many different activities
Your activities should be independent enough that you shouldn't need to know when your entire application is in the background. It sounds like you have other design issues that we can't help you with without more specifics.
I suggest managing your data on an activity-by-activity basis. This is suggested in the android docs.
For any activity that alters your persistent state, save that state when leaving the activity.
From http://developer.android.com/reference/android/app/Activity.html
onPause() is where you deal with the user leaving your activity. Most importantly, any changes made by the user should at this point be committed (usually to the ContentProvider holding the data).
This thread is pretty old, just to say onSaveInstanceState of activity is triggered when app is on background or when the user press home button on device. So there, you can save state, on load it on onrestore and so on...
How can I tell that my application has been put in the background (i.e. none of my app's activities are visible anymore)? I need to determine this so that I can release resources shared among several of my activities (graphics, sound clips and a socket connection).
I've thought about keeping a global counter that's incremented in the activities' onStart() method, and decremented in onStop(). If the counter reaches zero, then all activities have been stopped and my app is running in the background. However I'm not sure if this is going to be 100% reliable. Also, I can't help but think that there must be a better way of doing this.
You shouldn't need to know this, but to answer you:
in your main activity:
public boolean inBackground;
#Override
public void onPause()
{
inBackground=true;
super.onPause();
}
#Override
public void onResume()
{
inBackground=false;
super.onResume();
}
Aren't you after the OnPause()/OnResume() events?
http://developer.android.com/reference/android/app/Activity.html#onPause()
http://developer.android.com/reference/android/app/Activity.html#onResume()
See http://developer.android.com/guide/topics/fundamentals.html#lcycles for an overview.
You could use a global counter assuming it is kept in persistent storage. Always keep in mind the system is free to unload and reload activities from device RAM based on pressure from other apps so instance variables of activities are probably not a good choice to house that data.
I think the Android way of handling a scenario like yours would be to manage your connection state in a service and use persistent storage to monitor application state.
If you need this functionality maybe your architecture is not well designed. Each activity must be in some way "standalone" so when it's stopped release any data associate with it. If you need to store some persistant data between activities use sql or some other data storage and if you need some shared resources between activities put them in service. Try to isolate any coupling between activities.
I haven't tried this myself yet, but I think the following would work.
Create your own custom Activity class that extends Activity (as suggested in this SO question).
Ensure all your activites extend your custom Activity class.
#Override the onStop() method (as per the Activity life cycle docs).
Have onStop() call the utility method below (code based on Droid-Fu project) to figure out if your app is now in the background.
My worry is there could be some timing windows when your last activity closes before its new activity (also i your app) launches, but hopefully that is avoidable.
public static boolean isApplicationInBackground(Context context)
{
ActivityManager am =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty())
{
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName()))
{
return true;
}
}
return false;
}
Let us know how you get on as I might need to implement this feature too!
Update: I've done some quick testing of this code.
It seems to work fine when pressing the home key to exit the application, as the running task changes to ComponentInfo{com.motorola.blur.home/com.motorola.blur.home.HomeActivity} on my device. However, the code doesn't detect the app as in the background when using the back button to exit the application (it still thinks my app is running).
This scenario can be detected by overriding onDestroy() in your top level activities, and checking isFinished() to confirm that the app is getting destroyed (rather than the activity being recreated, e.g. for an orientation change).