Is there any way to get different event for application in background and particular activity in background?
In other words when any activity goes to background the onPause() method called, is there any to find that whole application goes to background?
Is there any settings for Manifest file to close the application when its goes to background.
Thanks,
AndroidIT
To identify if the application is in background:
There is a much more simpler approach:
On a BaseActivity that all Activities extend:
protected static boolean isVisible = false;
#Override
public void onResume()
{
super.onResume();
setVisible(true);
}
#Override
public void onPause()
{
super.onPause();
setVisible(false);
}
Whenever you need to check if any of your application activities is in foreground just check isVisible();
To understand this approach check this answer of side-by-side activity lifecycle: Activity side-by-side lifecycle
If you want to kill your application when it goes to background you have several options:
Something like this: Remove or close your own Activity window from a Status Bar Notification Intent modified for what you want.
Explore: android:finishOnTaskLaunch and android:excludeFromRecents and how you can make logic to make this effect (have done it already)
I would assume that all your activities are launched by one of the other activities in your app. If that is the case perhaps your activities could set flag indicating it is launching an activity. Then when onpause() is called this flag will determine if the app is being move to the background or simply launching the next activity.
save the state of each activity in shared preferences. each activity will need its own field in the preference file. each time you onResume or onPause, update the correct preference.
or: every time you onResume or onPause send a service a notification via intent that X activity has paused/resumed. the service will keep track of application state this way
Related
I am trying to trigger an unlock screen when the app goes from the background to the foreground.
All my activities are extending a base class which overrides onPause + onResume.
The problem with onPause is that this method gets called even when you launch a new intent.
What is a reliable way of determining when an app becomes active?
Regards,
Tim
Looks like onResume() will do the job for you. As for the case of extending from a base class, do not forget to call super.onResume() so your onResume will end up looking like this :
public void onResume()
{
super.onResume();
// your stuff
}
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 an issue. For analytic purposes I need to track when the APP (not activity) is resumed. The problem I have now is that if I put the tracker on the OnResume event of an activity, it will get fired every time the user goes back and forth on different activities.
How can I avoid that? How can I track the real "Application Resume," (when user actually exits the app and come back) and not the activity resume?
Any ideas is greatly appreciated. Thanks.
I encountered the same problem and solved it by creating base activity :
public class mActivity extends Activity{
public static final String TAG = "mActivity";
public static int activities_num = 0;
#Override
protected void onStop() {
super.onStop();
activities_num--;
if(activities_num == 0){
Log.e(TAG,"user not longer in the application");
}
}
#Override
protected void onStart() {
super.onStart();
activities_num++;
}
}
all the other activities in my app inherited mActivity. When an activity is no longer visible than onStop is called. when activities_num == 0 than all activities are not visible (meaning the the user close the app or it passed to the background). When the user start the application (or restarting it from the background) onStart will be called (onStart is called when the activity is visible) and activities_num > 0. hopes it helps...
Use the Application object of your app (see http://developer.android.com/reference/android/app/Application.html). If you create a custom Application class and configure it in your AndroidManifest.xml file you can do something like this:
Start tracking in the onCreate() of the Application object.
Instrument all your Activities so their onPause() and onResume() methods check with the Application object and see if they are the first Activity to run, or if they are continuing a previously running instance of the app.
Stop tracking in the onDestroy() of the Application object.
To a certain degree most of the analytics packages (Flurry and their ilk) do something similar to this. You'll need to do a little state machine work to get this to work right, but it shouldn't be too complicated.
Instead of OnResume(), hook into the OnCreate() event of your main activity.
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();.
I would like to launch an intent when any of my activity is visible, otherwise I will put it up as a notification, and will be fired by the user.
To decide this, I need to know if any of my activity is front-most, how do I that?
I don't know that there's a method to get the currently displayed activity, but you could do something combining the Activity Lifecycle and a flag.
For the flag, if you've extended the Application class, that's probably a decent place to store it. For extending the application class, the top answer to this question has info. (d).
So probably keep track of the current active activity (or a flag that the activity is visible) in onResume/onPause or onStart/onStop depending on exactly what behavior you want.
Since you have multiple activities, you'll need a centroid place for storing the flag, which is why the Application makes sense. You can get the custom Application object by casting the application context (e.g. ((MyApplication)getApplicationContext()).isMyActivityActive).
You could extend Activity as well to help keep this code clean and contained.
If you're using a service you could bind to the service in every activity in the onStart/onStop (or onResume/onPause). If bound, you're visible.
You can ask for the running tasks from ActivityManager:
ActivityManager activityManager = (ActivityManager)getContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE));
From API docs:
Return a list of the tasks that are currently running, with the most
recent being first and older ones after in order.
So the first item on the list is the frontmost activity.
onResume() called && onPause() not called = visible.
Have a public static Activity currentlyVisible; in your Application subclass that will be updated by your activities (set to the instance in onResume() and nulled in onPause()). Or invent a less ugly variant of a registry.
You could use onWindowFocusChanged(boolean hasFocus) place this in a superclass of your activities to launch the intent if it has focus.
Instead of using Activity manager there is a simple trick which you can do through code. If you observe the activity cycle closely, the flow between two activities and foreground to background is as follows. Suppose A and B are two activities.
When transition from A to B: 1. onPause() of A is called 2. onResume() of B is called 3. onStop() of A is called when B is fully resumed
When app goes into background: 1. onPause() of A is called 2. onStop() of A is called
You can detect your background event by simply putting a flag in activity.
Make an abstract activity and extend it from your other activities, so that you wont have to copy paste the code for all other activities wherever you need background event.
In abstract activity create flag isAppInBackground.
In onCreate() method: isAppInBackground = false;
In onPause() method: isAppInBackground = false;
In onStop() method: isAppInBackground = true;
You just to need to check in your onResume() if isAppInBackground is true.
n after you check your flag then again set isAppInBackground = false
For transition between two activities since onSTop() of first will always called after second actvity resumes, flag will never be true and when app is in background, onStop() of activity will be called immediately after onPause and hence the flag will be true when you open the app later on.