-
Star
(142)
You must be signed in to star a gist -
Fork
(41)
You must be signed in to fork a gist
-
-
Save steveliles/11116937 to your computer and use it in GitHub Desktop.
| package com.sjl.util; | |
| import android.app.Activity; | |
| import android.app.Application; | |
| import android.content.Context; | |
| import android.os.Bundle; | |
| import android.os.Handler; | |
| import android.util.Log; | |
| import java.util.List; | |
| import java.util.concurrent.CopyOnWriteArrayList; | |
| /** | |
| * Usage: | |
| * | |
| * 1. Get the Foreground Singleton, passing a Context or Application object unless you | |
| * are sure that the Singleton has definitely already been initialised elsewhere. | |
| * | |
| * 2.a) Perform a direct, synchronous check: Foreground.isForeground() / .isBackground() | |
| * | |
| * or | |
| * | |
| * 2.b) Register to be notified (useful in Service or other non-UI components): | |
| * | |
| * Foreground.Listener myListener = new Foreground.Listener(){ | |
| * public void onBecameForeground(){ | |
| * // ... whatever you want to do | |
| * } | |
| * public void onBecameBackground(){ | |
| * // ... whatever you want to do | |
| * } | |
| * } | |
| * | |
| * public void onCreate(){ | |
| * super.onCreate(); | |
| * Foreground.get(this).addListener(listener); | |
| * } | |
| * | |
| * public void onDestroy(){ | |
| * super.onCreate(); | |
| * Foreground.get(this).removeListener(listener); | |
| * } | |
| */ | |
| public class Foreground implements Application.ActivityLifecycleCallbacks { | |
| public static final long CHECK_DELAY = 500; | |
| public static final String TAG = Foreground.class.getName(); | |
| public interface Listener { | |
| public void onBecameForeground(); | |
| public void onBecameBackground(); | |
| } | |
| private static Foreground instance; | |
| private boolean foreground = false, paused = true; | |
| private Handler handler = new Handler(); | |
| private List<Listener> listeners = new CopyOnWriteArrayList<Listener>(); | |
| private Runnable check; | |
| /** | |
| * Its not strictly necessary to use this method - _usually_ invoking | |
| * get with a Context gives us a path to retrieve the Application and | |
| * initialise, but sometimes (e.g. in test harness) the ApplicationContext | |
| * is != the Application, and the docs make no guarantees. | |
| * | |
| * @param application | |
| * @return an initialised Foreground instance | |
| */ | |
| public static Foreground init(Application application){ | |
| if (instance == null) { | |
| instance = new Foreground(); | |
| application.registerActivityLifecycleCallbacks(instance); | |
| } | |
| return instance; | |
| } | |
| public static Foreground get(Application application){ | |
| if (instance == null) { | |
| init(application); | |
| } | |
| return instance; | |
| } | |
| public static Foreground get(Context ctx){ | |
| if (instance == null) { | |
| Context appCtx = ctx.getApplicationContext(); | |
| if (appCtx instanceof Application) { | |
| init((Application)appCtx); | |
| } | |
| throw new IllegalStateException( | |
| "Foreground is not initialised and " + | |
| "cannot obtain the Application object"); | |
| } | |
| return instance; | |
| } | |
| public static Foreground get(){ | |
| if (instance == null) { | |
| throw new IllegalStateException( | |
| "Foreground is not initialised - invoke " + | |
| "at least once with parameterised init/get"); | |
| } | |
| return instance; | |
| } | |
| public boolean isForeground(){ | |
| return foreground; | |
| } | |
| public boolean isBackground(){ | |
| return !foreground; | |
| } | |
| public void addListener(Listener listener){ | |
| listeners.add(listener); | |
| } | |
| public void removeListener(Listener listener){ | |
| listeners.remove(listener); | |
| } | |
| @Override | |
| public void onActivityResumed(Activity activity) { | |
| paused = false; | |
| boolean wasBackground = !foreground; | |
| foreground = true; | |
| if (check != null) | |
| handler.removeCallbacks(check); | |
| if (wasBackground){ | |
| Log.i(TAG, "went foreground"); | |
| for (Listener l : listeners) { | |
| try { | |
| l.onBecameForeground(); | |
| } catch (Exception exc) { | |
| Log.e(TAG, "Listener threw exception!", exc); | |
| } | |
| } | |
| } else { | |
| Log.i(TAG, "still foreground"); | |
| } | |
| } | |
| @Override | |
| public void onActivityPaused(Activity activity) { | |
| paused = true; | |
| if (check != null) | |
| handler.removeCallbacks(check); | |
| handler.postDelayed(check = new Runnable(){ | |
| @Override | |
| public void run() { | |
| if (foreground && paused) { | |
| foreground = false; | |
| Log.i(TAG, "went background"); | |
| for (Listener l : listeners) { | |
| try { | |
| l.onBecameBackground(); | |
| } catch (Exception exc) { | |
| Log.e(TAG, "Listener threw exception!", exc); | |
| } | |
| } | |
| } else { | |
| Log.i(TAG, "still foreground"); | |
| } | |
| } | |
| }, CHECK_DELAY); | |
| } | |
| @Override | |
| public void onActivityCreated(Activity activity, Bundle savedInstanceState) {} | |
| @Override | |
| public void onActivityStarted(Activity activity) {} | |
| @Override | |
| public void onActivityStopped(Activity activity) {} | |
| @Override | |
| public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} | |
| @Override | |
| public void onActivityDestroyed(Activity activity) {} | |
| } |
Good job. Thanks!
Doesn't work for hybrid applications such: Cordova, Unity, Nativescript, react Native
Thank you for you hard work. I had a nightmare trying to flag when I went Background to Foreground with crashes on resume with fragments.
This helps massively.
good , thanks
🙌
Fantastic
thanks a lot
@steveliles Thanks a lot! I have a question, If I use this source code in my commercial application then, Is there any license like a MIT, Apache something? Plz, let me know :)
I think we have some issues, When I request Permissions on my device, it's onBecameForeground and onBecameBackground
public class App extends Application implements Foreground.Listener {
@Override
public void onCreate(){
super.onCreate();
//ForeGround & Background
Foreground.init(this).addListener(this);
}
@Override
public void onBecameForeground() {
Log.d("Application","onBecameForeground");
}
@Override
public void onBecameBackground() {
Log.d("Application","onBecameBackground");
}
}
I think you can simplify it like this
public class AppLifecycleListener implements Application.ActivityLifecycleCallbacks {
private int numStarted;
private boolean isForeground;
@Override
public void onActivityStarted(Activity activity) {
if (numStarted == 0) {
isForeground = true;
}
numStarted++;
}
@Override
public void onActivityStopped(Activity activity) {
numStarted--;
if (numStarted == 0) {
isForeground = false;
}
}
}
you saved my day
Thanks @j796160836 for the solution, I had no idea why it was falling over :)
Forget that and just use ProcessLifecycleOwner from the Android Architecture Components. It's dead simple to use and it also handles when a permission dialog is displayed
class MyApplication : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForegrounded() {
Log.d(TAG, "In foreground")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackgrounded() {
Log.d(TAG, "In background")
}
}
It actually works. Great job!
Thanks lot
@hegazy Thank you!
Good job, mate! Thank you!