0

I want to determine if my app is on the screen or not, i.e. when user clicks the home button or locks screen I want to receive a one-time event that my app has gone into the background. And when user opens my app or unlocks screen I want to receive a one-time event that app has appeared on the screen.

onPause, onResume, onStart, onStop methods of the Activity is not what I'm looking. When the device screen is being locked/unlocked these methods are called multiple times. And sometimes when screen is unlocked and my app is on the screen I receive onStop/onPause. This is a bad scenario for my use case.
onWindowFocusChanged is called when the app opens any Dialog. This is also a bad scenario.

Is there another variant how to solve the problem?

ilyamuromets
  • 403
  • 1
  • 7
  • 18

3 Answers3

2

Assume you are using AndroidX for your project, then you can use ProcessLifecycleOwner to determine the app has gone or appeared on the screen.

ProcessLifecycleOwner

Class that provides lifecycle for the whole application process.

It is useful for use cases where you would like to react on your app coming to the foreground or going to the background and you don't need a milliseconds accuracy in receiving lifecycle events.

Using in your code:

1.Create a class that extends from Application class.

public class MyApplication extends Application {

    private final MyLifecycleObserver observer = new MyLifecycleObserver();

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(observer);
    }

    class MyLifecycleObserver implements LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        public void onAppMoveToForeground() {
            Log.d("MyLifecycleObserver", "My app moves to foreground.");
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        public void onMoveAppToBackground() {
            Log.d("MyLifecycleObserver", "My app moves to background.");
        }
    }
}

2.Add android:name=".MyApplication" in your AndroidManifest.xml file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidx">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Community
  • 1
  • 1
Son Truong
  • 13,661
  • 5
  • 32
  • 58
0

Lock:

You can listen to broadcast intent ACTION_SCREEN_OFF Listening for ACTION_SCREEN_OFF

Home Button:

@Override
protected void onUserLeaveHint()
{
    Log.d("onUserLeaveHint","Home button pressed");
    super.onUserLeaveHint();
}

or use intent-filter

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
suhotrub
  • 118
  • 1
  • 7
0

In an old application, I used to Application.ActivityLifecycleCallbacks

Here is an example

public class LifecycleHandler implements Application.ActivityLifecycleCallbacks {

    private Context mContext;

    public LifecycleHandler(Context context) {
        mContext = context;
    }

    private int resumed;
    private int stopped;

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        if (resumed == stopped) {
            //application is being foregrounded
        }
        ++resumed;
    }

    public void onActivityPaused(Activity activity) {
    }

    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    public void onActivityStarted(Activity activity) {
    }

    public void onActivityStopped(Activity activity) {
        ++stopped;
        if (resumed == stopped) {
            //application is being backgrounded
        }
    }
}

Then, I register it in my application object

public class MyApplication extends Application {

    @Override
    public void onCreate() {

        super.onCreate();

        //...

        registerActivityLifecycleCallbacks(new LifecycleHandler(this));

        //...
    }

And voilà !

Bruno
  • 3,872
  • 4
  • 20
  • 37