I'm trying to determine when my app is being resumed after the user closed it, in any way, pressing home button, back button or switching to another app.
What I need to do is to set a boolean when the app goes in background, so, when it is resumed, I know that it was in background before and I can act accordingly.
I tried to use onResume and onPause methods in activities to know when the app goes in background and it is then resumed, but as only one activity can be alive at at time, I had no success. When an activity is paused, this doesn't mean that the app went to background, because another activity could have been launched, but the onResume event of that activity will trigger only after the previous one has paused.
I've also tried to list all the apps in foreground, but with no success, if I put my app in background resuming another app, my app always results to be in the foreground.
I read that since Android 4 there is a new method to know when the app is in foreground, but I need my app to be compatible with Android 3.0 devices too.
Here is the code I tried putting in every single activity (MyApp is my Application name):
#Override
protected void onResume() {
super.onResume();
MyApp.isPaused = false;
}
#Override
protected void onPause() {
super.onPause();
MyApp.isPaused = true;
}
This is also my attempt to list all the apps in foreground:
ActivityManager activityManager = (ActivityManager)((Activity) currentContext).getSystemService( ACTIVITY_SERVICE );
List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for(RunningAppProcessInfo appProcess : appProcesses){
if(appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
if(appProcess.processName.equals("com.xxx.myapp")) {
Log.i("MyApp", "it's in foreground");
}
Log.i("MyApp", appProcess.processName);
}
}
This class provides a singleton to determine "the activity in background" status. It uses a timer with a threshold(i.e. 0.3s) to determine the activity is went to background or not.
One thing has to point out is that if the user resumes to the activity within the threshold (i.e. 0.3s), this test will be failed.
If you have a better solution, please share with us :)
Ref: https://gist.github.com/steveliles/11116937
You are absolutely correct :) Because only one activity can be alive at a time so you need something which remains alive through out the application life cycle :) like Application instance itself or you can also make use of shared preference for that matter. But seriously using shared prefference for checking lifecycle is wrong choice if you ask me.
If I was in your position I would have gone for Application class :) Here is code if you want to do the same :)
import android.app.Application;
/**
* Created by sandeepbhandari on 3/3/16.
*/
public class AppService extends Application{
private static AppService sInstance;
public static boolean isGoingToBackGround=false;
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
public static AppService getInstance() {
return sInstance;
}
}
In all your activities onPause just set
AppService service = AppService.getInstance();
service.isGoingToBackGround =true;
And in onResume check the same variablethats all :) and yeah if you want to use your application class rather than default Application you have to make change to manifest.xml
<application
android:name=".AppService"
Thats all :)
Override onTrimMemory(int level) in your Application. Might not be the prettiest way, but it has worked for me.
You will get
TRIM_MEMORY_BACKGROUND = 40;
when your application went into the Background.
You can make Application class inside your project to save state of your project. When any activity goes to pause call on pause respectively while on resume call on resume method and save state of the inside this class. Even if one activity goes on pause another on resume your class will know exact state of the application. Or another way you can save applicaton state in shared preference in each activity can change its value.
i trust there is no need for u to post a code... that being said...
start by logging every implemented methods onCreate(), onPause(), onDestroy(), and other well reputed Activity methods...
but back button does not just pause it kills, thus onCreate is called most
and check onStart() too.
public class CustomApplication extends Application {
private static boolean activityVisible;
#Override
public void onCreate() {
super.onCreate();
}
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
}
and in your all activities set
#Override
protected void onResume() {
super.onResume();
CustomApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
CustomApplication.activityPaused();
}
and in your manifest
<application
android:name=".CustomApplication"
by using onResume() i can check if an activity is foreground or not. My problem is this onResume() is fire each time even if i come from another activity to this activity.
So my main problem is ,if i minimizing the app by home button I want execute some code in each activity when app is come foreground BUT not using onResume().
I found an answer like this How to know in BroadcastReceiver if App is running on foreground? but i dont know how to register this receiver in android menifest to get the trigger when app is visible.
Please give me some tips how can i overcome this solution or code snippet which can help me. Thanks in advance :)
One thing to do what you want is to count the number of times onStart/onStop is called in your application. This will help you determine if you transitioned to your activity from inside or outside your application.
You must extend Application then create/register ActivityLifecycleCallbacks within that class. Also, make sure to specify the new Application class you created in the AndroidManifest.
Now, the trick is to keep a count variable in onActivityStarted/onActivityStopped to determine whether your Activity was navigated to from inside or outside the application.
Say you have 2 Activities in your app: FirstActivity & SecondActivity.
If you navigate from FirstActivity to SecondActivity the lifecycle calls will happen in this order: FirstActivity.onStart() > SecondActivity.onStart(), resulting in a count of 1.
If you navigate from outside your application, you will only see FirstActivity.onStart(), so the count is 0. This is all assuming you check the count after super.onStart() is called.
So, by checking count against 0/1 you can tell if your activity was launched from within the application or outside the application.
/**
* Extending the application class lets you use ActivityLifecycleCallbacks to
* keep track of all lifecycle callbacks in your application.
*/
public class MyApplication extends Application implements ActivityLifecycleCallbacks {
private int count = 0;
//Register activity lifecycle callbacks in onCreate
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
void onActivityStarted(Activity activity) {
count++;
}
void onActivityStopped(Activity activity) {
count--;
}
/**
* Use this method in your Activities to test if the activity was
* transitioned to from outside the application.
*
* If you call this method in Activity.onResume(), then count should be
* compared to 0. If you call this method in Activity.onStart() but
* *before* calling super.onStart(), then count should be compared to 0.
*
* However, if you call this method after super.onStart(), then count
* should be compared to 1.
*/
public boolean cameFromOutsideApplication() {
return count == 0;
}
//Don't need to use the rest of the activity lifecycle callbacks
void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
void onActivityDestroyed(Activity activity) {
}
void onActivityPaused(Activity activity) {
}
void onActivityResumed(Activity activity) {
}
void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
}
You may gain some more information here as well but it does not use ActivityLifecycleCallbacks which is easier to use.
If you want to register your receiver you can use the following code,
<receiver
android:name="com.package.name.ReceiverClassName"
android:enabled="true" >
</receiver>
I was wondering how to keep a record of launched activites for logging purposes. what broadcast receiver I have to subscribe to intercept this intent? or what intent-filter to use? I figure that I must use some type of long-running service in the background.
My first objetive is to track main-focus applications, some sort of history.
Want to get finally some similar to:
- Launched app com.android.xxx
- Launched app xx.yy.zz
- App xx.yy.zz lost focus
Thanks in advance
EDIT - Just see that app MyAppRank , that does exactly what i mean
What i'm able to figure out from your question is that you want to keep track of all the activities when they are launched in your application. If that is correct, the solution may work for you:
Crate a BaseActivity which all of your Activities should extend
public class BaseActivity extends Activity
{
private Activity activity;
public static final String INTENTFILTER_TRACK_MY_ACTIVITIES="INTENTFILTER_TRACK_MY_ACTIVITIES";
public static final String INTENTFILTER_REMOVE_MY_ACTIVITIES="INTENTFILTER_REMOVE_MY_ACTIVITIES";
public void setActivity(Activity act)
{
activity = act;
}
public Activity getActivity()
{
return activity;
}
#Override protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Intent intent = new Intent();
intent.setAction(INTENTFILTER_TRACK_MY_ACTIVITIES);
intent.putExtra("activityName", activity.getClass().getSimpleName());
sendBroadcast(intent);
}
#Override protected void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
Intent intent = new Intent();
intent.setAction(INTENTFILTER_REMOVE_MY_ACTIVITIES);
intent.putExtra("activityName", activity.getClass().getSimpleName());
sendBroadcast(intent);
setActivity(null);
}
}
Now extend above BaseActivity for all your activities. i.e instead of extending your Activities should extend BaseActivity and call setActivity(this); in onCreate like below:
public class MyActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setActivity(this);
//write your other code form here
}
}
3.Then write a BroadcastReceiver like below:
class TrackActivitiesReceiver extends BroadcastReceiver
{
private static final Object SEPERATOR = ",";// use , as seperator
String sb="";
#Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equalsIgnoreCase(BaseActivity.INTENTFILTER_TRACK_MY_ACTIVITIES))
{
sb+=intent.getStringExtra("activityName");
sb+=SEPERATOR;
}
else if(intent.getAction().equalsIgnoreCase(BaseActivity.INTENTFILTER_REMOVE_MY_ACTIVITIES))
{
sb=sb.replace(intent.getStringExtra("activityName")+SEPERATOR, "");
}
}}
4Finally, Register above Receiver in your AndroidManifest.xml
<receiver
android:name="TrackActivitiesReceiver"
android:exported="false" >
<intent-filter>
<action android:name="INTENTFILTER_TRACK_MY_ACTIVITIES" />
</intent-filter>
</receiver>
Hope this solves your problem. cheers!
There are no Intents broadcast when applications are started or when applications come to the foreground. There isn't anything that you can hook into as a listener to get these events.
The way you can do this (which is the way apps like MyAppRank do it) is to use the methods of the ActivityManager:
getRunningTasks()
getRunningAppProcesses()
getRecentTasks()
You create a Service which runs all the time and at regular intervals calls methods of the ActvityManager to determine which task is in the foreground and you can "infer" what the user has done (or is doing). It isn't an exact science.
Note: You will need android.permission.GET_TASKS and none of this works anymore as of API 21 (Android 5, Lollipop). As of API 21 the security has been tightened and an application can only get information about its own tasks, not other tasks in the system.
I'm trying to make a certain function to start only when a user,
Opens the app for the first time,
Goes back to an app from home.
But not start if the user switches between activities within the app.
I have looked through this topic,and the best answer is to use singleTask with onNewIntent(). So, if a user is goes back to the app from Home, a onNewIntent call with the launcher intent passed to it can be used.
However, here is my code:
public class AdMobSDK_DFP_Interstitial extends Activity implements AdListener {
private static final String MOBMAX_INTERSTITIAL_AD_UNIT_ID = "/7732/test_portal7/android_app1_test_portal7/splash_banner_android_app1_test_portal7";
private DfpInterstitialAd interstitialAd;
private int num = 0;
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
Log.d("flow", "onNewIntent");
}
If I switch between different activities in the app, onNewIntent() is always called, which is the same as I go back to the app from Home.
First thing you can do is to implement your own "Application" object and have it run the needed function when it is created.
public class MyApplication extends Application {
#Override
public void onCreate() {
// Call your function
}
}
Your application object will be live as long as your app is alive (any activity/service is still running), but note that the Application object is not destroyed immediately when the user presses "Home", and might stay alive for a while and a user can return to it without the function being called.
If you need this function to run as part of your main activity, just save a flag in your Application context :
public boolean alreadyDisplayed = false; and then in your activity's onStart you can just call
if ((MyApplication)getApplication().alreadyDisplayed ) {
// Call your function
(MyApplication)getApplication().alreadyDisplayed = true;
}
** If this solution is not enough for you and you need to call your function every time your main activity is displayed from the home page you'll need to do something not as nice... one suggestion I can give you is to implement the same Application object but this time with an "open activity" counter:
public class MyApplication extends Application {
public int mActivityCounter = 0;
}
Then you can increment this counter on every onStart of activity in your app and decrement on every onStop (of course this can be done by implementing a class MyActivity and make all your relevant activities inherit it. Then you can use this counter to know if there are any other activities opened. Note that you'll have to make sure the access to this counter is synchronized and work your way with it as you need.
I hope this helps...
I am doing a status bar notification in my android app that is triggered by c2dm. I don't want to display the notification if the app is running. How do you determine if the app is running and is in the foreground?
Alternately, you can check with the ActivityManager what tasks are running by getRunningTasks method. Then check with the first task(task in the foreground) in the returned List of tasks, if it is your task. Here is the code example:
public Notification buildNotification(String arg0, Map<String, String> arg1) {
ActivityManager activityManager = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager
.getRunningTasks(Integer.MAX_VALUE);
boolean isActivityFound = false;
if (services.get(0).topActivity.getPackageName().toString()
.equalsIgnoreCase(appContext.getPackageName().toString())) {
isActivityFound = true;
}
if (isActivityFound) {
return null;
} else {
// write your code to build a notification.
// return the notification you built here
}
}
And don't forget to add the GET_TASKS permission in the manifest.xml file in order to be able to run getRunningTasks() method in the above code:
<uses-permission android:name="android.permission.GET_TASKS" />
p/s : If agree this way, please to note that this permission now is deprecated.
Make a global variable like private boolean mIsInForegroundMode; and assign a false value in onPause() and a true value in onResume().
Sample code:
private boolean mIsInForegroundMode;
#Override
protected void onPause() {
super.onPause();
mIsInForegroundMode = false;
}
#Override
protected void onResume() {
super.onResume();
mIsInForegroundMode = true;
}
// Some function.
public boolean isInForeground() {
return mIsInForegroundMode;
}
This is a pretty old post but still quite relevant. The above accepted solution may work but is wrong. As Dianne Hackborn wrote:
These APIs are not there for applications to base their UI flow on, but to do things like show the user the running apps, or a task manager, or such.
Yes there is a list kept in memory for these things. However, it is off in another process, managed by threads running separately from yours, and not something you can count on (a) seeing in time to make the correct decision or (b) have a consistent picture by the time you return. Plus the decision about what the "next" activity to go to is always done at the point where the switch is to happen, and it is not until that exact point (where the activity state is briefly locked down to do the switch) that we actually know for such what the next thing will be.
And the implementation and global behavior here is not guaranteed to remain the same in the future.
The correct solution is to implement : ActivityLifeCycleCallbacks.
This basically needs an Application Class and the handler can be set in there to identify the state of your activities in the app.
As Vinay says, probably the best solution (to support newer android versions, 14+) is to use ActivityLifecycleCallbacks in the Application class implementation.
package com.telcel.contenedor.appdelegate;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;
/** Determines global app lifecycle states.
*
* The following is the reference of activities states:
*
* The <b>visible</b> lifetime of an activity happens between a call to onStart()
* until a corresponding call to onStop(). During this time the user can see the
* activity on-screen, though it may not be in the foreground and interacting with
* the user. The onStart() and onStop() methods can be called multiple times, as
* the activity becomes visible and hidden to the user.
*
* The <b>foreground</b> lifetime of an activity happens between a call to onResume()
* until a corresponding call to onPause(). During this time the activity is in front
* of all other activities and interacting with the user. An activity can frequently
* go between the resumed and paused states -- for example when the device goes to
* sleep, when an activity result is delivered, when a new intent is delivered --
* so the code in these methods should be fairly lightweight.
*
* */
public class ApplicationLifecycleManager implements ActivityLifecycleCallbacks {
/** Manages the state of opened vs closed activities, should be 0 or 1.
* It will be 2 if this value is checked between activity B onStart() and
* activity A onStop().
* It could be greater if the top activities are not fullscreen or have
* transparent backgrounds.
*/
private static int visibleActivityCount = 0;
/** Manages the state of opened vs closed activities, should be 0 or 1
* because only one can be in foreground at a time. It will be 2 if this
* value is checked between activity B onResume() and activity A onPause().
*/
private static int foregroundActivityCount = 0;
/** Returns true if app has foreground */
public static boolean isAppInForeground(){
return foregroundActivityCount > 0;
}
/** Returns true if any activity of app is visible (or device is sleep when
* an activity was visible) */
public static boolean isAppVisible(){
return visibleActivityCount > 0;
}
public void onActivityCreated(Activity activity, Bundle bundle) {
}
public void onActivityDestroyed(Activity activity) {
}
public void onActivityResumed(Activity activity) {
foregroundActivityCount ++;
}
public void onActivityPaused(Activity activity) {
foregroundActivityCount --;
}
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public void onActivityStarted(Activity activity) {
visibleActivityCount ++;
}
public void onActivityStopped(Activity activity) {
visibleActivityCount --;
}
}
And in Application onCreate() method:
registerActivityLifecycleCallbacks(new ApplicationLifecycleManager());
Then ApplicationLifecycleManager.isAppVisible() or ApplicationLifecycleManager.isAppInForeground() would be used to know the desired state.
Since API 16 you can do it like this:
static boolean shouldShowNotification(Context context) {
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
if (myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
return true;
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
// app is in foreground, but if screen is locked show notification anyway
return km.inKeyguardRestrictedInputMode();
}
FYI, if you use Gadenkan solution (which is great!!) don't forget to add
<uses-permission android:name="android.permission.GET_TASKS" />
to the manifest.
Slightly cleaned up version of Gadenkan's solution. Put it any Activity, or maybe a base class for all your Activities.
protected boolean isRunningInForeground() {
ActivityManager manager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1);
if (tasks.isEmpty()) {
return false;
}
String topActivityName = tasks.get(0).topActivity.getPackageName();
return topActivityName.equalsIgnoreCase(getPackageName());
}
To be able to call getRunningTasks(), you need to add this in your AndroidManifest.xml:
<uses-permission android:name="android.permission.GET_TASKS"/>
Do note what ActivityManager.getRunningTasks() Javadoc says though:
Note: this method is only intended for debugging and presenting task
management user interfaces. This should never be used for core logic
in an application, such as deciding between different behaviors based
on the information found here. Such uses are not supported, and will
likely break in the future.
Update (Feb 2015)
Note that getRunningTasks() was deprecated in API level 21!
As of LOLLIPOP, this
method is no longer available to third party applications: the
introduction of document-centric recents means it can leak person
information to the caller. For backwards compatibility, it will still
return a small subset of its data: at least the caller's own tasks,
and possibly some other tasks such as home that are known to not be
sensitive.
So what I wrote earlier is even more relevant:
In many cases you can probably come up with a better solution. For example, doing something in onPause() and onResume(), perhaps in a BaseActivity for all your Activities.
(In our case we didn't want an offline alert activity to be launched if we are not in the foreground, so in BaseActivity onPause() we simply unsubscribe from the RxJava Subscription listening for "went offline" signal.)
Following up on Gadenkan's reply I needed something like this so I could tell if my app wasn't running in the foreground, but I needed something that was app wide and didn't require me setting/unsetting flags throughout my application.
Gadenkan's code pretty much hit the nail on the head but it wasn't in my own style and felt it could be tidier, so in my app its condensed down to this.
if (!context.getPackageName().equalsIgnoreCase(((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).topActivity.getPackageName()))
{
// App is not in the foreground
}
(Side note: You can just remove the ! if you want the check to work the other way around)
Although with this approach you need the GET_TASKS permission.
Starting support library version 26 you can use ProcessLifecycleOwner to determine app current state, just add it to your dependencies like described here, for example:
dependencies {
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// alternatively - Lifecycles only (no ViewModel or LiveData).
// Support library depends on this lightweight import
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin
}
, Now you can query ProcessLifecycleOwner whenever you want to check app state, for example to check if app is running in foreground you just have to do this:
boolean isAppInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
if(!isAppInForeground)
//Show Notification in status bar
Based on the various answers and comments, here is a more inlined version that you can add to a helper class:
public static boolean isAppInForeground(Context context) {
List<RunningTaskInfo> task =
((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
.getRunningTasks(1);
if (task.isEmpty()) {
return false;
}
return task
.get(0)
.topActivity
.getPackageName()
.equalsIgnoreCase(context.getPackageName());
}
As mentioned in other answers you need to add the following permission to your AndroidManifest.xml .
<uses-permission android:name="android.permission.GET_TASKS"/>
I would like to add that a safer way to do this - than checking if your app is in the background before creating a notification - is to just disable and enable the Broadcast Receiver onPause() and onResume() respectively.
This method gives you more control in the actual application logic and is not likely to change in the future.
#Override
protected void onPause() {
unregisterReceiver(mHandleMessageReceiver);
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
}
I found a more simpler and accurate way to check if the application is in foreground or background by mapping the activities to boolean.
Check the complete gist here
Here's the code for nice simple solution described above by #user2690455 . Although it looks a bit verbose, you'll see overall it's actually quite light-weight
In my case we also use AppCompatActivity, so I had to have 2 base classes.
public class BaseActivity extends Activity {
/**
* Let field be set only in base class
* All callers must use accessors,
* and then it's not up to them to manage state.
*
* Making it static since ..
* 1. It needs to be used across two base classes
* 2. It's a singleton state in the app
*/
private static boolean IS_APP_IN_BACKGROUND = false;
#Override
protected void onResume() {
super.onResume();
BaseActivity.onResumeAppTracking(this);
BaseActivity.setAppInBackgroundFalse();
}
#Override
protected void onStop() {
super.onStop();
BaseActivity.setAppInBackgroundTrue();
}
#Override
protected void onPause() {
super.onPause();
BaseActivity.setAppInBackgroundFalse();
}
protected static void onResumeAppTracking(Activity activity) {
if (BaseActivity.isAppInBackground()) {
// do requirements for returning app to foreground
}
}
protected static void setAppInBackgroundFalse() {
IS_APP_IN_BACKGROUND = false;
}
protected static void setAppInBackgroundTrue() {
IS_APP_IN_BACKGROUND = true;
}
protected static boolean isAppInBackground() {
return IS_APP_IN_BACKGROUND;
}
}
This is useful only when you want to perform some action just when your activity starts and its where you want to check if app is in foreground or background.
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.
There is one more scenario though in this approach.
If any of your app screen is already open and you put the mobile idle then after some time mobile will go into sleep mode and when you unlock mobile, it will be treated at background event.
Here is a method that I use (and supporting method):
private boolean checkIfAppIsRunningInForeground() {
ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
for(ActivityManager.RunningAppProcessInfo appProcessInfo : activityManager.getRunningAppProcesses()) {
if(appProcessInfo.processName.contains(this.getPackageName())) {
return checkIfAppIsRunningInForegroundByAppImportance(appProcessInfo.importance);
}
}
return false;
}
private boolean checkIfAppIsRunningInForegroundByAppImportance(int appImportance) {
switch (appImportance) {
//user is aware of app
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND:
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE:
return true;
//user is not aware of app
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND:
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY:
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE:
case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE:
default:
return false;
}
}
There is no global callback for this, but for each activity it is onStop(). You don't need to mess with an atomic int. Just have a global int with the number of started activities, in every activity increment it in onStart() and decrement it in onStop().
Follow this
public static boolean isAppRunning(Context context) {
// check with the first task(task in the foreground)
// in the returned list of tasks
ActivityManager activityManager = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services =
activityManager.getRunningTasks(Integer.MAX_VALUE);
if
(services.get(0).topActivity.getPackageName().toString().equalsIgnoreCase(context.getPackageName().toString()))
{
return true;
}
return false;
}
The previous approaches mentioned here are not optimal. The task based approach requires a permission that might not be desired and "Boolean" approach is prone to concurrent modification mess ups.
The approach I use and which (I believe) works quite well in most cases:
Have a "MainApplication" class to track activity count in AtomicInteger:
import android.app.Application;
import java.util.concurrent.atomic.AtomicInteger;
public class MainApplication extends Application {
static class ActivityCounter {
private static AtomicInteger ACTIVITY_COUNT = new AtomicInteger(0);
public static boolean isAppActive() {
return ACTIVITY_COUNT.get() > 0;
}
public static void activityStarted() {
ACTIVITY_COUNT.incrementAndGet();
}
public static void activityStopped() {
ACTIVITY_COUNT.decrementAndGet();
}
}
}
And create a base Activity class that other activities would extend:
import android.app.Activity;
import android.support.annotation.CallSuper;
public class TestActivity extends Activity {
#Override
#CallSuper
protected void onStart() {
MainApplication.ActivityCounter.activityStarted();
super.onStart();
}
#Override
#CallSuper
protected void onStop() {
MainApplication.ActivityCounter.activityStopped();
super.onStop();
}
}