Is there any way to handle when my android application goes into background and back?
I want to use notification service for a on-line game - I use a service, which shows an alert when something happens in the game. I want alerts to show only if my application is active (on the foreground), so I need to start my service when application goes foreground and stop it when application goes background.
Note that I cannot use Activity.OnPause/OnResume methods. I have many activities in my application, and if I'll handle OnPause/OnResume, it is possible in a moment, when a user swtches one activity to another, application will look like background, thorough it will be foreground actually
Note that I cannot use Activity.OnPause/OnResume methods. I have many
activities in my application, and if I'll handle OnPause/OnResume, it
is possible in a moment, when a user swtches one activity to another,
application will look like background, thorough it will be foreground
actually
Why don't you write a base class that extends Activity and enables or disables the service in these methods? After that extend all your activities from this base activity.
All you have to do is call the superclass method if you override these methods in your activties, e.g. by calling super.onResume() inside onResume(), to make sure these get still called. If you don't override them, everything works directly.
Not a clean way of doing this that I know of but,
You could perhaps send an Intent to your Service onCreate() and onPause() with a unique identifier.
You Service can then start a timer (with a delay which will be longer than the difference between onPause and onCreate being called in each activity) which, if not notified of an onCreate() within this time will set the Activity as "Paused".
If you add this functionality in a parent class which extends Activity you can then pull this same functionality into every class by extending that it rather than Activity (with the contract that you must call super.onCreate() and super.onPause() in each respective method).
Problem solved in a following way (C# code, mono for android)
class MyService : Service{
OnSomethingHappened(){
ActivityManager am = (ActivityManager) GetSystemService(ActivityService);
if(am.RunningAppProcesses.Any((arg) =>
arg.ProcessName == "myprocessname" &&
arg.Importance == ActivityManager.RunningAppProcessInfo.ImportanceForeground
)){
Trace("FOREGROUND!!!!");
}else{
Trace("BACKGROUND!!!!");
}
}
}
Related
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.
I need my application to do 2 network calls when ever the app is started for the 1st time, when it has been killed and started again as well as when it has been placed in the background then returned.
I know I can put it in my "MainActivity" onCreate/onResume. I have a class that extends Application which is where I am initialising logging and crash reporting, but I noticed there is no onResume method, which from my understand is the method that is called when the application comes from the background.
Where would be the best place to do these 2 network calls to update certain aspects in my app when the app is started for the 1st time, started when killed and resumed when it comes back from the background.
FYI. The reason I don't want it to go in my "MainActivity" is that I don't want these network calls to be called when ever i return to the MainActivity from another screen in the app, only when the user returns to the app?
Thanks
The use case of calling whenever the app returns from background is by implementing Activity Life Cycle methods in your Application class:
public class myApp extends Application implements Application.ActivityLifecycleCallbacks {
...
}
In this case you make sure that whenever an onPause() is called a corresponding onResume() should also be called (i.e. normal screen switching). If not, then you know that your app is now in background. The next callback to onResume() should mean that it has come to foreground again and you can make your network call.
I am needing help to determine the right approach. I want to make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed. I want to call this method from a central class called Main which extends Application. The reason for that is, that I need to use several activites and I want to call the backup Method only when needed (like described when the whole application gets destroyed or interrupted by another application). I try to avoid calling this backup method in every activity in their onPause() methods.
I thought about starting a service in the onCreate() method of the application, and starting the backup method when the service gets destroyed. But this won't help in the case of an interrupt, as far as I understood the logic behind services. And also the service doesn't seem to start. startService(new Intent(getApplicationContext(), BackupService.class)); Furthermore I don't think it is a good approach to just use the onDestroy() method of a service, this is not what the service class is made for in my opinion.
So summarizing my Question, do you know a better way then using a service, or if not do you know how I should use the service to be able to call a backup only at the point when the whole app (and not only an activity) is interrupted or destroyed.
First of all, if your service "doesn't seem to start", you are probably doing something wrong.
To accomplish your goal make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed:
There are three cases in general here.
If you want to do it in the activity layer:
To know when your application is crashed, you need to implement a custom handler to catch the uncaught exceptions.
To know when your activity is "interrupted", the only way is do it in onPause.
To know when your activity is "terminated", the only way is to do it in onDestroy.
This will require you to have a clear navigation and only do it in your "main activity", and all the other activity starts and comes back to it OR use a flag to indicate if the pause was caused by going to another activity.
If you want to do it in the service layer: (Your way of doing it onDestroy won't allow you to detect interrupted case since you will have to start service sticky to keep it running)
You will have to set up a flag on each activity onBind (you will have to bind it and unbind it) to know if it is a crash/interrupt/termination, which will complicate other part of your code.
To avoid running repetitive code, you will have to create a generic base class and extend your other activities from it.
I use this approach to play background music in one of my games, but I guess it works in this scenario as well.
Use a boolean flag to indicate whether or not your app is launching another part of your app.
boolean movingInApp = false;
....
movingInApp = true;
Intent intent...
.....
public void onPause() {
if(!movingInApp) {
//start service
}
}
public void onResume() {
movingInApp = false;
//Stop service
}
By setting the value of movingInApp to true before launching any intent etc, you can prevent your app from starting the service. Remember to set it to false again later in your onResume() method. If the system makes your app go to the background, this will be false, and your service will be started.
Why dont u have all of your activities extend a base activity which in turn extend the android activity class
I the base activity have backupDB method in the onPause
Therefore u dont have to put it in every activity pause method
In my app I need to call code whenever the app closes (pauses) and then run code again whenever the app starts again (resumes). For example, I call a web service that syncs the data whenever the app starts or exits. This is easy in iOS because of the central app resume and suspend methods.
I understand the OnPause and OnResume in the Activity, however, is there a central way to handle this? The user could leave the app on Activity3 and come back later, or be in another screen, etc. I'd hate to have to have the same code in every Activity's OnPause and OnResume to handle the "app" startup and shutdown code routines.
Any suggestions?
Thank you.
You could make a common Activity which just handles onResume() and onPause() in a certain way and then make every Activity extend from that one instead of Activity directly.
I would consider subclassing Activty, have each of your activities extend that and just do what you need to when any of them pause or resume.
You could use some static members in an Application class that your new activity base uses to track state or store whatever you need.
Also, Application class has an onCreate() method which will run each time the application is started. There is no pause or resume for Application, however.
Creating a main Activity that is extended by all your other activities and override the onPause and onResume.
But the problem you will face if you want to extend another Activity class such as a ListActivity.
Another approach is to create a new class that extends application and override its onCreate and create a static method that acts as onPause and manually call it by each of your activities
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();.