Best alternative to Stop an Activity started from a Service - android

I started an activity with the following code from my service:
Intent cmActivityIntent = new Intent(getApplicationContext(), CallManagementActivity.class);
cmActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(cmActivityIntent);
In the app's manifest the launchMode of the activity is defined as android:launchMode="singleTask".
I've been looking for ways of stopping the activity on the service's onDestroy() but I haven't been able to find any documentation that can help me. And I've only found one way of doing it.
I've seen the aproach of checking on the serviceif the activity is instanced using an activity-class-static-property (public static boolean isInstanced) and sending another intent to the activity with a FINISH_ACTIVITY extra if it is. Then, on the activity's onNewIntent() the flag would be checked and the activity would be finished if the flag was included.
This approach doesn't feel right to me, since intents are supposed to be used start activities and not stopping them.
Does someone know any other way of how to acomplish this?

Many alternatives have been given to solve this issue:
Use an Intent and set an Extra.
Send a broadcast intent from the Service and register a BroadcastReceiver on the Activity.
Use the LocalBroadcastManager (similar to previous alternative)
Bind the Activity to the Service and pass it a Messenger so the Service can use it to communicate with the Activity.
None of them have I found a good solution, in fact, since the service is only accesible from the package, the solution I'm sticking with is the Observer Pattern.
Next you'll find the code I used. The activities implement the Observer interface (my own) and the service the abstract class ObservableService.
ObservableService:
public abstract class ObservableService extends Service {
#Override
public void onCreate() {
super.onCreate();
serviceStarted = true;
observers = new ArrayList<Observer>();
}
#Override
public void onDestroy() {
super.onDestroy();
serviceStarted = false;
}
//---------------------------------------------------------
//
// Singleton methods
//
//---------------------------------------------------------
/**
* Flag set to <code>true</code> if the service is running and
* <code>false</code> if not.
*/
private static boolean serviceStarted;
/**
* Used to check if the service is started.
* #return <code>true</code> if the service is running and <code>false</code>
* if not.
*/
public static boolean isServiceStarted() {
return serviceStarted;
}
//---------------------------------------------------------
//
// Observable methods an constants
//
//---------------------------------------------------------
/**
* Used to notify the observers that the service has been stopped.
*/
public static String UPDATE_TYPE_SERVICE_STOPPED = "service_stopped";
protected static ArrayList<Observer> observers;
public static void addObserver(Observer observer) {
observers.add(observer);
}
public static void removeObserver(Observer observer) {
observers.remove(observer);
}
protected static void notifyObservers(String updateType) {
for (Observer observer : observers) {
observer.onObservableUpdate(updateType);
}
}
}
Observer:
public interface Observer {
public void onObservableUpdate(String updateType);
}
The activities just register themselves as observers at onResume() and unregister at onPause(). The isServiceStarted() is used to finish the activity if the service is already stopped.
#Override
protected void onResume() {
super.onResume();
if (InCallService.isServiceStarted()) {
InCallService.addObserver(this);
} else {
this.finish();
}
}
#Override
protected void onPause() {
super.onPause();
InCallService.removeObserver(this);
}
public void onObservableUpdate(String updateType) {
if (updateType.equals(ObservableService.UPDATE_TYPE_SERVICE_STOPPED)) {
this.finish();
}
}
I chose this because I found it to be a very simple and high-performance alternative.

Related

Access TextViews from broadcast receiver

In my broadcast receiver, I'm accessing a method that calls another method which is in my MainActivity class. The method from my MainActivity class uses variables that are set in the onCreate() method.
The problem I'm having is that when the broadcast receiver tries to access this method when the app has been closed, it finds the variables null because the onCreate method hasn't ran to set the variables.
Should I try to trigger the onCreate method from my broadcast receiver, or do I have this whole setup wrong? I tried to condense the code a bit so it's not too long but below you can see the gist of what I'm trying to do.
The error I'm getting is that "text" and "ringer" are null when trying to setText. This only happens when the broadcast receiver runs while the app is closed and not running.
WifiScanCompleteReceiver code:
public class WifiScanCompleteReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
...
}
public static void activate() {
...
MainActivity.statusText();
}
}
Activity code:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
...
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.state);
ringer = (TextView)findViewById(R.id.mode);
state = mSettings.getString("state", "init");
mode = mSettings.getInt("ringer", 0);
statusText();
}
public static void statusText() {
text.setText(state);
if (mode == 1) {
ringer.setText("Vibrate");
} else if (mode == 2) {
ringer.setText("Normal");
} else {
ringer.setText("Unkown");
}
}
}
Instead of accessing the TextView from the receiver, I just triggered the main activity as a service with context.startService(Intent); and that seemed to get me what I wanted.
I needed to trigger the code in my main activity to run even if the main activity had been stopped. So this solved that for me.
You can solve this using interface:
1) Create an interface
interface MyListener {
public void doSomething();
}
2) Initialize the Listener in BroadcastReceiver
public class WifiScanCompleteReceiver extends BroadcastReceiver {
private MyListener listener;
public void onReceive(Context context, Intent intent) {
listener = (MyListener)context;
listener.doSomething(); // Call interface method
}
}
3) Implement interface in the Activity and override the method
public class MainActivity extends Activity {
// Your Activity code
public static void statusText() {
text.setText(state);
if (mode == 1) {
ringer.setText("Vibrate");
} else if (mode == 2) {
ringer.setText("Normal");
} else {
ringer.setText("Unkown");
}
}
#Override
public void doSomething(){
statusText();
}
}
Relevant Link:
If you want to read the advantage of using interface Read this
Its not a good approach to call activity's method directly from the receiver. App will crash in a case when your activity is not visible, but due to receiver's call it will try to execute activity's code.
You can use local broadcast here. Instead of calling activity's method from receiver send local broadcast, which you need to register in your activity and in receiver of local broadcast call your activity method. This method(Activity's method) call from local broadcast will only execute when your activity will be visible and will not result in app crash.

Callback once Activity in another process has started?

If I do startActivity() on an Activity in another process; is there a good way to receive a callback at the starting point (starting the new Activity form a background service) that the new Activity really has started? I mean I can make a broadcast but that seems lame. Is there a better way for this?
Basically what you are asking about is ipc. Google it for more info.
To achieve this you need to create a sevice class and bind the two activities to it.
An example Service class would look like this.
public class MyService extends Service{
//create a handler that will be used to handle messages
//this is just an example. Use static handlers
final Handler handler=new Handler(){
public void handleMessage(Message msg){
//I've just created a static feild.Check below.
MyFirstActivity.activity.seconActivityStarted();
}
}
//create a Messenger object
Messenger messenger=new Messenger(handler);
#Override
public IBinder onBind(Intent intent){
return messenger.getBinder()
}
}
Now things are simple.
Now you have to bind the first activity with the servie.
public class MyFirstActivity extends AppCompatActivity{
//for the time being I'll just create a static field that will be used.
//you can use an interface
static MyFirstActivity activity;
//create a ServiceConnection
ServiceConnection connection=new ServiceConnection(/*contents of the service connection */);
public void onStart(){
super.onStart();
activity=this;
bindService(new Intent(this,MyService.class),connection,Context.BIND_AUTO_CREATE));
}
//following method will be called by the handler in the service
public void secondActivityStarted(){
//some code
}
//you have to handle the activity lifecycle with the bound service.
//right now its described here
}
Now the second activity
public class SecondActivity extends AppCompatActivity{
//create a ServiceConnection
ServiceCOnnection serviceConnection=new ServiceConnection(){
//call the handler at onServiceConnected
public void onServiceCOnnected(ComponentName name, IBinder service){
Messenger messenger=new Messenger(service);
//compose a Message object as you like
messenger.send(new Message());
}
};
//bind this activity to the same service
public void onStart(){
super.onStart();
bindService(new Intent(this,com.package.name.MySerice.class),serviceConnection,Context.BIND_AUTO_CREATE);
}
}
That's it. Modify this according to the requirements.
P.S.Above mentioned code is just working structure.
If you do startActivity() on an Activity in same or another process (and assuming the second activity starts), the calling Activity will go in to first PAUSED, and then STOPPED state. Which means no callback would be processed. However, you can call startActivityForResult() instead of startActivity() and receive onActivityResult() callback.
Add a class MyApplication that extends Application and mention in your Manifest too and than put two boolean variables in it.
private static boolean activityVisible;
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
public static boolean isActivityVisible() {
return activityVisible;
}
and so now you can use call activityPaused() when you do startActivity() on onPause() and onStop() of current activity, and when you return back to same activity do call activityResumed() in overriden onResume() method.
Now, by using MyApplication.isActivityVisible() you can get to know whether your Activity is running or paused.

How to keep GPS turned on when switching between activities but off when when "home" is pressed

I am trying to figure out the best way to implement Listener to location with the onResume and onPause.
Best I can do not it to turn it off on onPause and reconnect on onResume. But then I keep having disconnect-reconnect when all I want is for the GPS to stay on for the duration of the application. When Home is pressed (or another application is interrupting) then GPS can be downed off for battery saving.
Any ideas?
Thanks.
Your question can be generalized to "How do I tell when my app moves into/out of the foreground?" I have used the following approach successfully in two different apps that needed the ability to discern this.
When you change activities, you should see the following sequence of lifecycle events:
Activity A onPause()
Activity B onCreate()
Activity B onStart()
Activity B onResume()
Activity A onStop()
As long as both of these activities are yours, you can make a singleton class designed to track whether your app is the foreground app or not.
public class ActivityTracker {
private static ActivityTracker instance = new ActivityTracker();
private boolean resumed;
private boolean inForeground;
private ActivityTracker() { /*no instantiation*/ }
public static ActivityTracker getInstance() {
return instance;
}
public void onActivityStarted() {
if (!inForeground) {
/*
* Started activities should be visible (though not always interact-able),
* so you should be in the foreground here.
*
* Register your location listener here.
*/
inForeground = true;
}
}
public void onActivityResumed() {
resumed = true;
}
public void onActivityPaused() {
resumed = false;
}
public void onActivityStopped() {
if (!resumed) {
/* If another one of your activities had taken the foreground, it would
* have tripped this flag in onActivityResumed(). Since that is not the
* case, your app is in the background.
*
* Unregister your location listener here.
*/
inForeground = false;
}
}
}
Now make a base activity that interacts with this tracker. If all of your activities extend this base activity, your tracker will be able to tell you when you move to the foreground or the background.
public class BaseActivity extends Activity {
private ActivityTracker activityTracker;
public void onCreate(Bundle saved) {
super.onCreate(saved);
/* ... */
activityTracker = ActivityTracker.getInstance();
}
public void onStart() {
super.onStart();
activityTracker.onActivityStarted();
}
public void onResume() {
super.onResume();
activityTracker.onActivityResumed();
}
public void onPause() {
super.onPause();
activityTracker.onActivityPaused();
}
public void onStop() {
super.onStop();
activityTracker.onActivityStopped();
}
}

How to notify Activity about changes in global variable in Application?

I have a IntentService that updates a global variabel in a extended Application class. In several of mine Activities I need to know when the variable is changed.
Do I have to implement a BroadcastReceiver in all my Activities(and send a intent from my service) or is there a simpler way to notify my activities?
Thank you!
I have also faced this type of problem. Broadcast receiver in one of the Solution. But i am not satisfied with that.So, I tried with another metod.You can find more details in object observer pattern in andrdoid,refer this link.
public class TestActivity extends Activity implements Observer {
BaseApp myBase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myBase = (BaseApp) getApplication();
myBase.getObserver().addObserver(this);
myBase.getObserver().setValue(10);
}
#Override
public void update(Observable observable, Object data) {
// This method is notified after data changes.
Toast.makeText(this, "I am notified" + myBase.getObserver().getValue(),
0).show();
}
}
public class Test extends Observable
{
private int value=2;
/**
* #return the value
*/
public int getValue()
{
return value;
}
/**
* #param value
* the value to set
*/
public void setValue(int value)
{
this.value = value;
setChanged();
notifyObservers();
}
}
package app.tabsample;
import android.app.Application;
public class BaseApp extends Application {
Test mTest;
#Override
public void onCreate() {
super.onCreate();
mTest = new Test();
}
public Test getObserver() {
return mTest;
}
}
Yes, BroadcastReceivers were designed for just this. That said, why not just make a single parent class which has a BroadcastReceiver and all the associated logic? Then the only thing your other activities have to do is simply inherit from that parent class.
Note that you should also set some sort of global variable in persistent storage (like a shared preference) every time you send our a Broadcast. That way, if one of your activities isn't in the foreground when the Broadcast is sent, it can check the variable in persistent storage when it comes back in the onResume() method and act accordingly.

Checking if an Android application is running in the background

By background, I mean none of the application's activities are currently visible to the user?
There are few ways to detect whether your application is running in the background, but only one of them is completely reliable:
The right solution (credits go to Dan, CommonsWare and NeTeInStEiN)
Track visibility of your application by yourself using Activity.onPause, Activity.onResume methods. Store "visibility" status in some other class. Good choices are your own implementation of the Application or a Service (there are also a few variations of this solution if you'd like to check activity visibility from the service).
Example
Implement custom Application class (note the isActivityVisible() static method):
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
Register your application class in AndroidManifest.xml:
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
Add onPause and onResume to every Activity in the project (you may create a common ancestor for your Activities if you'd like to, but if your activity is already extended from MapActivity/ListActivity etc. you still need to write the following by hand):
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}
Update
ActivityLifecycleCallbacks were added in API level 14 (Android 4.0). You can use them to track whether an activity of your application is currently visible to the user. Check Cornstalks' answer below for the details.
The wrong one
I used to suggest the following solution:
You can detect currently foreground/background application with ActivityManager.getRunningAppProcesses() which returns a list of RunningAppProcessInfo records. To determine if your application is on the foreground check RunningAppProcessInfo.importance field for equality to RunningAppProcessInfo.IMPORTANCE_FOREGROUND while RunningAppProcessInfo.processName is equal to your application package name.
Also if you call ActivityManager.getRunningAppProcesses() from your application UI thread it will return importance IMPORTANCE_FOREGROUND for your task no matter whether it is actually in the foreground or not. Call it in the background thread (for example via AsyncTask) and it will return correct results.
While this solution may work (and it indeed works most of the time) I strongly recommend to refrain from using it. And here's why. 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 sure what the next thing will be.
And the implementation and global behavior here is not guaranteed to remain the same in the future.
I wish I had read this before I posted an answer on the SO, but hopefully it's not too late to admit my error.
Another wrong solution
Droid-Fu library mentioned in one of the answers uses ActivityManager.getRunningTasks for its isApplicationBroughtToBackground method. See Dianne's comment above and don't use that method either.
GOOGLE SOLUTION - not a hack, like previous solutions. Use ProcessLifecycleOwnerKotlin:
class ArchLifecycleApp : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
//App in background
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
// App in foreground
}
}
Java:
public class ArchLifecycleApp extends Application implements LifecycleObserver {
#Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppBackgrounded() {
//App in background
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppForegrounded() {
// App in foreground
}
}
in app.gradle
dependencies {
...
implementation "android.arch.lifecycle:extensions:1.1.0"
//New Android X dependency is this -
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
}
allprojects {
repositories {
...
google()
jcenter()
maven { url 'https://maven.google.com' }
}
}
You can read more about Lifecycle related architecture components here - https://developer.android.com/topic/libraries/architecture/lifecycle
DO NOT USE THIS ANSWER
user1269737's answer is the proper (Google/Android approved) way to do this. Go read their answer and give them a +1.
I'll leave my original answer here for posterity's sake. This was the best available back in 2012, but now Android has proper support for this.
Original answer
The key is using ActivityLifecycleCallbacks (note that this requires Android API level 14 (Android 4.0)). Just check if the number of stopped activities is equal to the number of started activities. If they're equal, your application is being backgrounded. If there are more started activities, your application is still visible. If there are more resumed than paused activities, your application is not only visible, but it's also in the foreground. There are 3 main states that your activity can be in, then: visible and in the foreground, visible but not in the foreground, and not visible and not in the foreground (i.e. in the background).
The really nice thing about this method is that it doesn't have the asynchronous issues getRunningTasks() does, but you also don't have to modify every Activity in your application to set/unset something in onResumed()/onPaused(). It's just a few lines of code that's self contained, and it works throughout your whole application. Plus, there are no funky permissions required either.
MyLifecycleHandler.java:
public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
// I use four separate variables here. You can, of course, just use two and
// increment/decrement them instead of using four and incrementing them all.
private int resumed;
private int paused;
private int started;
private int stopped;
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
++resumed;
}
#Override
public void onActivityPaused(Activity activity) {
++paused;
android.util.Log.w("test", "application is in foreground: " + (resumed > paused));
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityStarted(Activity activity) {
++started;
}
#Override
public void onActivityStopped(Activity activity) {
++stopped;
android.util.Log.w("test", "application is visible: " + (started > stopped));
}
// If you want a static function you can use to check if your application is
// foreground/background, you can use the following:
/*
// Replace the four variables above with these four
private static int resumed;
private static int paused;
private static int started;
private static int stopped;
// And these two public static functions
public static boolean isApplicationVisible() {
return started > stopped;
}
public static boolean isApplicationInForeground() {
return resumed > paused;
}
*/
}
MyApplication.java:
// Don't forget to add it to your manifest by doing
// <application android:name="your.package.MyApplication" ...
public class MyApplication extends Application {
#Override
public void onCreate() {
// Simply add the handler, and that's it! No need to add any code
// to every activity. Everything is contained in MyLifecycleHandler
// with just a few lines of code. Now *that's* nice.
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
}
}
#Mewzer has asked some good questions about this method that I'd like to respond to in this answer for everyone:
onStop() is not called in low memory situations; is that a problem here?
No. The docs for onStop() say:
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.
The key here is "keep your activity's process running..." If this low memory situation is ever reached, your process is actually killed (not just your activity). This means that this method of checking for backgrounded-ness is still valid because a) you can't check for backgrounding anyway if your process is killed, and b) if your process starts again (because a new activity is created), the member variables (whether static or not) for MyLifecycleHandler will be reset to 0.
Does this work for configuration changes?
By default, no. You have to explicitly set configChanges=orientation|screensize (| with anything else you want) in your manifest file and handle the configuration changes, or else your activity will be destroyed and recreated. If you do not set this, your activity's methods will be called in this order: onCreate -> onStart -> onResume -> (now rotate) -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume. As you can see, there is no overlap (normally, two activities overlap very briefly when switching between the two, which is how this backgrounding-detection method works). In order to get around this, you must set configChanges so that your activity is not destroyed. Fortunately, I've had to set configChanges already in all of my projects because it was undesirable for my entire activity to get destroyed on screen rotate/resize, so I've never found this to be problematic. (thanks to dpimka for refreshing my memory on this and correcting me!)
One note:
When I've said "background" here in this answer, I've meant "your app is no longer visible." Android activities can be visible yet not in the foreground (for example, if there's a transparent notification overlay). That's why I've updated this answer to reflect that.
It's important to know that Android has a weird limbo moment when switching activities where nothing is in the foreground. For this reason, if you check if your application is in the foreground when switching between activities (in the same app), you'll be told you're not in the foreground (even though your app is still the active app and is visible).
You can check if your app is in the foreground in your Activity's onPause() method after super.onPause(). Just remember the weird limbo state I just talked about.
You can check if your app is visible (i.e. if it's not in the background) in your Activity's onStop() method after super.onStop().
Starting support library version 26 you can use ProcessLifecycleOwner, just add it to your dependency 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
}
And then just query ProcessLifecycleOwner whenever you want for app state, examples:
// Check if app is in background
ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED;
// Check if app is in foreground
ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
Since Android API 16 there is a simple way to check if app is in foreground. It may not be foolproof, but no methods on Android are foolproof. This method is good enough to use when your service receives update from server and has to decide whether to show notification, or not (because if UI is foreground, user will notice the update without notification).
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
isInBackground = myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
Idolon's answer is error prone and much more complicated althought repeatead here check android application is in foreground or not? and here Determining the current foreground application from a background task or service
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
I tried the recommended solution that uses Application.ActivityLifecycleCallbacks and many others, but they didn't work as expected. Thanks to Sarge, I came up with a pretty easy and straightforward solution that I am describing below.
They key of the solution is the fact of understanding that if we have ActivityA and ActivityB, and we call ActivityB from ActivityA (and not call ActivityA.finish), then ActivityB's onStart() will be called before ActivityA onStop().
That's also the main difference between onStop() and onPause() that none did mention in the articles I read.
So based on this Activity's Lifecycle behavior, you can simply count how many times did onStart() and onPause() got called in your program. Note that for each Activity of your program, you must override onStart() and onStop(), in order to increment/decrement the static variable used for counting. Below is the code implementing this logic. Note that I am using a class that extends Application, so dont forget to declare on Manifest.xml inside Application tag: android:name=".Utilities", although it can be implemented using a simple custom class too.
public class Utilities extends Application
{
private static int stateCounter;
public void onCreate()
{
super.onCreate();
stateCounter = 0;
}
/**
* #return true if application is on background
* */
public static boolean isApplicationOnBackground()
{
return stateCounter == 0;
}
//to be called on each Activity onStart()
public static void activityStarted()
{
stateCounter++;
}
//to be called on each Activity onStop()
public static void activityStopped()
{
stateCounter--;
}
}
Now on each Activity of our program, we should override onStart() and onStop() and increment/decrement as shown below:
#Override
public void onStart()
{
super.onStart();
Utilities.activityStarted();
}
#Override
public void onStop()
{
Utilities.activityStopped();
if(Utilities.isApplicationOnBackground())
{
//you should want to check here if your application is on background
}
super.onStop();
}
With this logic, there are 2 possible cases:
stateCounter = 0 : The number of stopped is equal with the number of started Activities, which means that the application is running on the background.
stateCounter > 0 : The number of started is bigger than the number of stopped, which means that the application is running on the foreground.
Notice: stateCounter < 0 would mean that there are more stopped Activities rather than started, which is impossible. If you encounter this case, then it means that you are not increasing/decreasing the counter as you should.
You are ready to go. You should want to check if your application is on background inside onStop().
There is no way, short of you tracking it yourself, to determine if any of your activities are visible or not. Perhaps you should consider asking a new StackOverflow question, explaining what it is you are trying to achieve from a user experience, so we can perhaps give you alternative implementation ideas.
You can use ComponentCallbacks2 to detect if the app is in background. BTW this callback is only available in API Level 14 (Ice Cream Sandwich) and above.
You will get a call to the method:
public abstract void onTrimMemory (int level)
if the level is ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN then the app is in background.
You can implement this interface to an activity, service, etc.
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
#Override
public void onConfigurationChanged(final Configuration newConfig) {
}
#Override
public void onLowMemory() {
}
#Override
public void onTrimMemory(final int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// app is in background
}
}
}
Building on #Cornstalks answer to include a couple of useful features.
Extra features:
introduced singleton pattern so you can do this anywhere in the application: AppLifecycleHandler.isApplicationVisible() and AppLifecycleHandler.isApplicationInForeground()
added handling of duplicate events (see comments // take some action on change of visibility and // take some action on change of in foreground)
App.java
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(AppLifecycleHandler.getInstance());
}
}
AppLifecycleHandler.java
public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
private int resumed;
private int started;
private final String DebugName = "AppLifecycleHandler";
private boolean isVisible = false;
private boolean isInForeground = false;
private static AppLifecycleHandler instance;
public static AppLifecycleHandler getInstance() {
if (instance == null) {
instance = new AppLifecycleHandler();
}
return instance;
}
private AppLifecycleHandler() {
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
++resumed;
android.util.Log.w(DebugName, "onActivityResumed -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
setForeground((resumed > 0));
}
#Override
public void onActivityPaused(Activity activity) {
--resumed;
android.util.Log.w(DebugName, "onActivityPaused -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
setForeground((resumed > 0));
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityStarted(Activity activity) {
++started;
android.util.Log.w(DebugName, "onActivityStarted -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
setVisible((started > 0));
}
#Override
public void onActivityStopped(Activity activity) {
--started;
android.util.Log.w(DebugName, "onActivityStopped -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
setVisible((started > 0));
}
private void setVisible(boolean visible) {
if (isVisible == visible) {
// no change
return;
}
// visibility changed
isVisible = visible;
android.util.Log.w(DebugName, "App Visiblility Changed -> application is visible: " + isVisible);
// take some action on change of visibility
}
private void setForeground(boolean inForeground) {
if (isInForeground == inForeground) {
// no change
return;
}
// in foreground changed
isInForeground = inForeground;
android.util.Log.w(DebugName, "App In Foreground Changed -> application is in foreground: " + isInForeground);
// take some action on change of in foreground
}
public static boolean isApplicationVisible() {
return AppLifecycleHandler.getInstance().started > 0;
}
public static boolean isApplicationInForeground() {
return AppLifecycleHandler.getInstance().resumed > 0;
}
}
The best solution I have come up with uses timers.
You have start a timer in onPause() and cancel the same timer in onResume(), there is 1 instance of the Timer (usually defined in the Application class). The timer itself is set to run a Runnable after 2 seconds (or whatever interval you think is appropriate), when the timer fires you set a flag marking the application as being in the background.
In the onResume() method before you cancel the timer, you can query the background flag to perform any startup operations (e.g. start downloads or enable location services).
This solution allows you to have several activities on the back stack, and doesn't require any permissions to implement.
This solution works well if you use an event bus too, as your timer can simply fire an event and various parts of your app can respond accordingly.
If you turn on developer settings "Don't keep actvities" - check only count of created activites is not enough. You must check also isSaveInstanceState. My custom method isApplicationRunning() check is android app is running:
Here my work code:
public class AppLifecycleService implements Application.ActivityLifecycleCallbacks {
private int created;
private boolean isSaveInstanceState;
private static AppLifecycleService instance;
private final static String TAG = AppLifecycleService.class.getName();
public static AppLifecycleService getInstance() {
if (instance == null) {
instance = new AppLifecycleService();
}
return instance;
}
public static boolean isApplicationRunning() {
boolean isApplicationRunning = true;
if (getCountCreatedActvities() == 0 && !isSaveInstanceState()) {
isApplicationRunning = false;
}
return isApplicationRunning;
}
public static boolean isSaveInstanceState() {
return AppLifecycleService.getInstance().isSaveInstanceState;
}
public static int getCountCreatedActvities() {
return AppLifecycleService.getInstance().created;
}
private AppLifecycleService() {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
this.isSaveInstanceState = true;
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
++created;
}
#Override
public void onActivityDestroyed(Activity activity) {
--created;
}
#Override
public void onActivityResumed(Activity activity) { }
#Override
public void onActivityPaused(Activity activity) { }
#Override
public void onActivityStarted(Activity activity) { }
#Override
public void onActivityStopped(Activity activity) { }
}
To piggyback on what CommonsWare and Key have said, you could perhaps extend the Application class and have all of your activities call that on their onPause/onResume methods. This would allow you to know which Activity(ies) are visible, but this could probably be handled better.
Can you elaborate on what you have in mind exactly? When you say running in the background do you mean simply having your application still in memory even though it is not currently on screen? Have you looked into using Services as a more persistent way to manage your app when it is not in focus?
I did my own implementation of ActivityLifecycleCallbacks. I'm using SherlockActivity, but for normal Activity class might work.
First, I'm creating an interface that have all methods for track the activities lifecycle:
public interface ActivityLifecycleCallbacks{
public void onActivityStopped(Activity activity);
public void onActivityStarted(Activity activity);
public void onActivitySaveInstanceState(Activity activity, Bundle outState);
public void onActivityResumed(Activity activity);
public void onActivityPaused(Activity activity);
public void onActivityDestroyed(Activity activity);
public void onActivityCreated(Activity activity, Bundle savedInstanceState);
}
Second, I implemented this interface in my Application's class:
public class MyApplication extends Application implements my.package.ActivityLifecycleCallbacks{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
}
#Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
#Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
}
#Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
}
#Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
}
}
Third, I'm creating a class that extends from SherlockActivity:
public class MySherlockActivity extends SherlockActivity {
protected MyApplication nMyApplication;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
nMyApplication = (MyApplication) getApplication();
nMyApplication.onActivityCreated(this, savedInstanceState);
}
protected void onResume() {
// TODO Auto-generated method stub
nMyApplication.onActivityResumed(this);
super.onResume();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
nMyApplication.onActivityPaused(this);
super.onPause();
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
nMyApplication.onActivityDestroyed(this);
super.onDestroy();
}
#Override
protected void onStart() {
nMyApplication.onActivityStarted(this);
super.onStart();
}
#Override
protected void onStop() {
nMyApplication.onActivityStopped(this);
super.onStop();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
nMyApplication.onActivitySaveInstanceState(this, outState);
super.onSaveInstanceState(outState);
}
}
Fourth, all class that extend from SherlockActivity, I replaced for MySherlockActivity:
public class MainActivity extends MySherlockActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Now, in the logcat you will see the logs programmed in the Interface implementation made in MyApplication.
Offical docs:
The system distinguishes between foreground and background apps. (The definition of background for purposes of service limitations is distinct from the definition used by memory management; an app might be in the background as pertains to memory management, but in the foreground as pertains to its ability to launch services.) An app is considered to be in the foreground if any of the following is true:
It has a visible activity, whether the activity is started or paused.
It has a foreground service.
Another foreground app is connected to the app, either by binding to one of its services or by making use of one of its content providers. For example, the app is in the foreground if another app binds to its:
IME
Wallpaper service
Notification listener
Voice or text service
If none of those conditions is true, the app is considered to be in the background.
The only one correct solution:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
MyApp.mainActivity = this;
super.onCreate(savedInstanceState);
...
}
MyApp.java:
public class MyApp extends Application implements LifecycleObserver {
public static MainActivity mainActivity = null;
#Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onAppBackgrounded() {
// app in background
if (mainActivity != null) {
...
}
}
#OnLifecycleEvent(Lifecycle.Event.ON_START)
void onAppForegrounded() {
// app in foreground
if (mainActivity != null) {
...
}
}
}
No any solution work for me, however I propose a raw solution. This should work. If isAppBackground return false, then app must be in foreground.
public static boolean isAppBackground(Context context){
boolean isBackground=true;
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH){
List<ActivityManager.RunningAppProcessInfo> runningProcesses =activityManager.getRunningAppProcesses();
for(ActivityManager.RunningAppProcessInfo processInfo:runningProcesses){
if(processInfo.importance==ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
for(String activeProcess:processInfo.pkgList){
if(activeProcess.equals(context.getPackageName())){
isBackground = false;
}
}
}
}
}else{
List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
if(taskInfo.size()>0) {
ComponentName componentName = taskInfo.get(0).topActivity;
if(componentName.getPackageName().equals(context.getPackageName())){
isBackground = false;
}
}
}
return isBackground;
}
Activity gets paused when a Dialog comes above it so all the recommended solutions are half-solutions. You need to create hooks for dialogs as well.
I recommend reading through this page: http://developer.android.com/reference/android/app/Activity.html
In short, your activity is no longer visible after onStop() has been called.
Since it isn't already mentioned, I will suggest the readers to explore ProcessLifecycleOwner available through Android Architecture components
This code will check foreground and background in any condition:
Java Code:
private static boolean isApplicationForeground(Context context) {
KeyguardManager keyguardManager =
(KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager.isKeyguardLocked()) {
return false;
}
int myPid = Process.myPid();
ActivityManager activityManager =
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> list;
if ((list = activityManager.getRunningAppProcesses()) != null) {
for (ActivityManager.RunningAppProcessInfo aList : list) {
ActivityManager.RunningAppProcessInfo info;
if ((info = aList).pid == myPid) {
return info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
}
}
}
return false;
}
Kotlin Code:
private fun isApplicationForeground(context: Context): Boolean {
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
if (keyguardManager.isKeyguardLocked) {
return false
}
val myPid = Process.myPid()
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
var list: List<ActivityManager.RunningAppProcessInfo>
if (activityManager.runningAppProcesses.also { list = it } != null) {
for (aList in list) {
var info: ActivityManager.RunningAppProcessInfo
if (aList.also { info = it }.pid == myPid) {
return info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
}
}
}
return false
}
Simple and straight-forward answer:
override fun onPause() {
Log.i("APP LIFECYCLE", "App Enter BACKground")
isForeground = false
super.onPause()
}
override fun onResume() {
Log.i("APP LIFECYCLE", "App Enter FOREground")
isForeground = true
super.onResume()
}
Then just use the isForeground property of your activity to check the status.
Another solution for this old post (for those that it might help) :
<application android:name=".BaseApplication" ... >
public class BaseApplication extends Application {
private class Status {
public boolean isVisible = true;
public boolean isFocused = true;
}
private Map<Activity, Status> activities;
#Override
public void onCreate() {
activities = new HashMap<Activity, Status>();
super.onCreate();
}
private boolean hasVisibleActivity() {
for (Status status : activities.values())
if (status.isVisible)
return true;
return false;
}
private boolean hasFocusedActivity() {
for (Status status : activities.values())
if (status.isFocused)
return true;
return false;
}
public void onActivityCreate(Activity activity, boolean isStarting) {
if (isStarting && activities.isEmpty())
onApplicationStart();
activities.put(activity, new Status());
}
public void onActivityStart(Activity activity) {
if (!hasVisibleActivity() && !hasFocusedActivity())
onApplicationForeground();
activities.get(activity).isVisible = true;
}
public void onActivityWindowFocusChanged(Activity activity, boolean hasFocus) {
activities.get(activity).isFocused = hasFocus;
}
public void onActivityStop(Activity activity, boolean isFinishing) {
activities.get(activity).isVisible = false;
if (!isFinishing && !hasVisibleActivity() && !hasFocusedActivity())
onApplicationBackground();
}
public void onActivityDestroy(Activity activity, boolean isFinishing) {
activities.remove(activity);
if(isFinishing && activities.isEmpty())
onApplicationStop();
}
private void onApplicationStart() {Log.i(null, "Start");}
private void onApplicationBackground() {Log.i(null, "Background");}
private void onApplicationForeground() {Log.i(null, "Foreground");}
private void onApplicationStop() {Log.i(null, "Stop");}
}
public class MyActivity extends BaseActivity {...}
public class BaseActivity extends Activity {
private BaseApplication application;
#Override
protected void onCreate(Bundle state) {
application = (BaseApplication) getApplication();
application.onActivityCreate(this, state == null);
super.onCreate(state);
}
#Override
protected void onStart() {
application.onActivityStart(this);
super.onStart();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
application.onActivityWindowFocusChanged(this, hasFocus);
super.onWindowFocusChanged(hasFocus);
}
#Override
protected void onStop() {
application.onActivityStop(this, isFinishing());
super.onStop();
}
#Override
protected void onDestroy() {
application.onActivityDestroy(this, isFinishing());
super.onDestroy();
}
}
See the comment in the onActivityDestroyed function.
Works with SDK target version 14> :
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
public static int active = 0;
#Override
public void onActivityStopped(Activity activity) {
Log.i("Tracking Activity Stopped", activity.getLocalClassName());
active--;
}
#Override
public void onActivityStarted(Activity activity) {
Log.i("Tracking Activity Started", activity.getLocalClassName());
active++;
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
}
#Override
public void onActivityResumed(Activity activity) {
Log.i("Tracking Activity Resumed", activity.getLocalClassName());
active++;
}
#Override
public void onActivityPaused(Activity activity) {
Log.i("Tracking Activity Paused", activity.getLocalClassName());
active--;
}
#Override
public void onActivityDestroyed(Activity activity) {
Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
active--;
// if active var here ever becomes zero, the app is closed or in background
if(active == 0){
...
}
}
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
Log.i("Tracking Activity Created", activity.getLocalClassName());
active++;
}
}
You should use a shared preference to store the property and act upon it using service binding from your activities. If you use binding only, (that is never use startService), then your service would run only when you bind to it, (bind onResume and unbind onPause) that would make it run on foreground only, and if you do want to work on background you can use the regular start stop service.
I think this question should be more clear. When? Where? What is your specific situation you want to konw if your app is in background?
I just introduce my solution in my way.
I get this done by using the field "importance" of RunningAppProcessInfo class in every activity's onStop method in my app, which can be simply achieved by providing a BaseActivity for other activities to extend which implements the onStop method to check the value of "importance". Here is the code:
public static boolean isAppRunning(Context context) {
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> appProcesses = activityManager
.getRunningAppProcesses();
for (RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(context.getPackageName())) {
if (appProcess.importance != RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE) {
return true;
}
}
}
return false;
}
What about using getApplicationState().isInForeground() ?
In my opinion, many answers introduce a heavy load of code and bring lots of complexity and non-readability.
When people ask on SO how to communicate between a Service and a Activity, I usually advice to use the LocalBroadcastManager.
Why?
Well, by quoting the docs:
You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
It is more efficient than sending a global broadcast through the system.
Not in the the docs:
It does not require external libraries
The code is minimal
It's fast to implement and understand
No custom self-implemented callbacks / ultra-singleton / intra-process
pattern whatsoever...
No strong references on Activity, Application, ...
Description
So, you want to check if any of the Activity is currently in the foreground. You usually do that in a Service, or your Application class.
This means, your Activity objects become the sender of a signal (I'm on / I'm off). Your Service, on the other hand, becomes the Receiver.
There are two moments in which your Activity tells you if it's going in the foreground or in the background (yes only two... not 6).
When the Activity goes into the foreground, the onResume() method is triggered (also called after onCreate()).
When the Activity goes in the back, onPause() is called.
These are the moments in which your Activity should send the signal to your Service to describe its state.
In case of multiple Activity's, remember the an Activity goes into the background first, then another one comes into the foreground.
So the situation would be:*
Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON
The Service / Application will simply keep listening for those signals and act accordingly.
Code (TLDR)
Your Service must implement a BroadcastReceiver in order to listen for signals.
this.localBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// received data if Activity is on / off
}
}
public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")
Register the Receiver in Service::onCreate()
#Override
protected void onCreate() {
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
Un-register it in Service::onDestroy()
#Override
protected void onDestroy() {
// I'm dead, no need to listen to anything anymore.
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
Now your Activity's must communicated their state.
In Activity::onResume()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
In Activity::onPause()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
A very, very common situation
Developer: I want to send data from my Service and update the Activity. How do I check if the Activity is in the foreground?
There is usually no need to check if the Activity is in the foreground or not. Just send the data via LocalBroadcastManager from your Service. If the Activity is on, then it will respond and act.
For this very common situation, the Service becomes the sender, and the Activity implements the BroadcastReceiver.
So, create a Receiver in your Activity. Register it in onResume() and un-register it in onPause(). There is no need to use the other life-cycle methods.
Define the Receiver behavior in onReceive() (update ListView, do this, do that, ...).
This way the Activity will listen only if it's in the foreground and nothing will happen if it's in the back or is destroyed.
In case of multiple Activity's, whichever Activity is on will respond (if they also implement the Receiver).
If all are in the background, nobody will respond and the signal will simply get lost.
Send the data from the Service via Intent (see code above) by specifying the signal ID.
Except for Multi-Window Support. It may be tricky (please test it if needed)...
fun isAppInForeground(): Boolean {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager ?: return false
val appProcesses = activityManager.runningAppProcesses ?: return false
val packageName = packageName
for (appProcess in appProcesses) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName == packageName) {
return true
}
}
return false
}
None of the answers quite fitted the specific case if you're looked to know if a specfic activity is in the forground and if you're an SDK without direct access to the Application. For me I was in background thread having just recieved a push notification for a new chat message and only want to display a system notification if the chat screen isn't in the foreground.
Using the ActivityLifecycleCallbacks that as been recommended in other answers I've created a small util class that houses the logic to whether MyActivity is in the Foreground or not.
class MyActivityMonitor(context: Context) : Application.ActivityLifecycleCallbacks {
private var isMyActivityInForeground = false
init {
(context.applicationContext as Application).registerActivityLifecycleCallbacks(this)
}
fun isMyActivityForeground() = isMyActivityInForeground
override fun onActivityPaused(activity: Activity?) {
if (activity is MyActivity) {
isMyActivityInForeground = false
}
}
override fun onActivityResumed(activity: Activity?) {
if (activity is MyActivity) {
isMyActivityInForeground = true
}
}
}

Categories

Resources