6

I'm actually using this code to check if the app in the onPause is going to the background or not.

public static boolean isApplicationSentToBackground(final Context context) {
    ActivityManager am = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE );
    List<RunningTaskInfo> tasks = am.getRunningTasks( 1 );
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get( 0 ).topActivity;
        String name = LockScreenActivity.class.getName();
        String topAPN = topActivity.getPackageName();
        String conAPN = context.getPackageName();

        if (topActivity.getClassName().equals( name ) || !topActivity.getPackageName().equals( context.getPackageName() )) {
            return true;
        }
    }
    return false;
}

This code has worked pretty well until now with Android 4.4. If now I check topAPN and conAPN they are equal (and they are always not equal when the app is sent to background on android <= 4.3).

Do you know how to solve this problem? Has something changed?

StErMi
  • 5,389
  • 5
  • 48
  • 71
  • What about some boolean, say inBackGround = false. And then you set it to true from the onPause and back to false from the onStart? – Noman Arain Nov 11 '13 at 16:42
  • The problem about that approach is that I need to know, in the activity if the app is going on background in order to display the service notification. onPause is going only to tell me if the app (until a possible onResume) is going not visible to the user. – StErMi Nov 11 '13 at 16:44
  • "Note: your activity will call onResume the first time the activity is started, so you might want to set a boolean in onPause to signal your app that it actually went to the background" I believe in background is same as not visible. http://stackoverflow.com/questions/5156067/catch-when-android-application-went-on-background – Noman Arain Nov 11 '13 at 16:50
  • Did you check this: http://stackoverflow.com/questions/3667022/android-is-application-running-in-background He is also saying that your approach maybe wrong. – Noman Arain Nov 11 '13 at 16:54
  • I know @NomanArain I already saw that post and I know that mine is not the correct (or safe) way to do that check but in onPause you don't know if your app is *really* on background, you just know if your Activity (where onPause is called) is not visible to the user anymore. That does not mean that your app is in background in that moment until you get or not an onResume. The best solution (that does not exists at the moment) will be if Android will provice a precise event for your app that will notify you if you are in background or foreground. – StErMi Nov 11 '13 at 17:03
  • I see what you're asking now. – Noman Arain Nov 11 '13 at 17:05
  • What about this? http://stackoverflow.com/a/13809991/1275777 – Noman Arain Nov 11 '13 at 17:10
  • That could be a possible solution but you have to disable the configuration change from the manifest otherwise you have the same problem of onPuase shifted on onDestroy (an onDestroy does not mean that your app is in background. Ondestroy can be called also on configuration change). Disabling configuration from manifest is a bad choise because you need to handle it manually by yourself – StErMi Nov 11 '13 at 17:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/40970/discussion-between-noman-arain-and-stermi) – Noman Arain Nov 11 '13 at 17:23
  • http://stackoverflow.com/q/4414171/2684 -> that's where you can get your answer. – Martin Marconcini Dec 06 '13 at 06:17
  • The reason why it doesn't work it's because it was completely unreliable: Read the docs: 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. – Martin Marconcini Dec 06 '13 at 06:18

2 Answers2

5

I was facing the same issue.I solved it for the new versions.Just use this code

public static boolean isApplicationSentToBackground(final Context context) {
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        if (!topActivity.getPackageName().equals(context.getPackageName())) {
            return true;
        }
    }
    return false;
}

And in onPause method call this function this way

 @Override
protected void onPause() {
    super.onPause();
    handler.sendMessage(new Message());
}

Handler handler=new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        if (DeviceManager.isApplicationSentToBackground(getApplicationContext())) {
          paused = true;
      }
        return false;
    }
});

I dont know the excat reason but may be because of diff thread in handler i m getting the correct value

sheetal
  • 3,014
  • 2
  • 31
  • 45
  • 1
    You should note that your paused boolean inside of the handleMessage override should be static. Otherwise putting the app into the background and returning will cause that boolean to reset. – portfoliobuilder Dec 16 '15 at 03:30
  • @portfoliobuilder yup it has to be static – sheetal Jan 12 '16 at 19:04
0

This code is working for android 4.4 i have declared used this method in onStop here it is:

// code for app goes in back

@Override
protected void onStop() {
super.onStop();

    if (AppConstants.isAppSentToBackground(getApplicationContext())) {
        // Do what ever you want after app close simply Close session

    }
}

    // Method to Check Our app is running or Not
    public static boolean isAppSentToBackground(final Context context) {

    try {
        ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        // The first in the list of RunningTasks is always the foreground
        // task.
        RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
        String foregroundTaskPackageName = foregroundTaskInfo.topActivity
                .getPackageName();// get the top fore ground activity
        PackageManager pm = context.getPackageManager();
        PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(
                foregroundTaskPackageName, 0);

        String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo
                .loadLabel(pm).toString();

        // Log.e("", foregroundTaskAppName +"----------"+
        // foregroundTaskPackageName);
        if (!foregroundTaskAppName.equals("Your App name")) {
            return true;
        }
    } catch (Exception e) {
        Log.e("isAppSentToBackground", "" + e);
    }
    return false;
}
Moubeen Farooq Khan
  • 2,875
  • 1
  • 11
  • 26
Smit Patel
  • 1,174
  • 3
  • 26
  • 40
  • This code is wrong. Don't use that, it's very inefficient and getRunningTasks is NOT intended for usage. From the docs: 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. – Martin Marconcini Dec 06 '13 at 06:16
  • @MartínMarconcini I gave the solution that I have used in my application if you don't want to use then it's your choice. And it's perfectly runs in all OS 2.2 to 4.4 – Smit Patel Dec 06 '13 at 09:10
  • 1
    The solution may work, but it's wrong in many ways, are you here to use a solution that is wrong or just wanna hack your way around and move? The documentation is clearly saying DO NOT USE THIS. I'm sorry but I'm here to write better code by learning from others and teaching others when possible. – Martin Marconcini Dec 06 '13 at 21:37
  • If the method is wrong then why Google has added to the documentation? – Smit Patel Dec 09 '13 at 07:34
  • Because it has a different usage. You are clearly using the method for the wrong purpose, as stated by the documentation. Please read this carefully instead of just copying and pasting code without really knowing what it does: http://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int) – Martin Marconcini Dec 09 '13 at 18:55
  • And while you are reading the documentation, notice the text in **bold** that reads: "Note: this method is only intended for debugging and presenting task management user interfaces." Then they clearly say: **This should never be used for core logic in an application** (emphasis mine). Notice I didn't even start talking about inefficiency yet… that's another subject and doesn't belong here anymore. – Martin Marconcini Dec 09 '13 at 18:58
  • Yes. The solution really depends on your target/min API level, but I suggest you dive into these answers: http://stackoverflow.com/questions/4414171/how-to-detect-when-an-android-app-goes-to-the-background-and-come-back-to-the-fo While you are at it, ignore the accepted answer because that's incorrect (it relies on onPause/onResume). The timed method works fantastically and doesn't cause false positives nor uses a debug method. Specifically this: http://stackoverflow.com/a/15573121/2684 (if you're under API 14). Read all the answers and comments, they are very informative. :) – Martin Marconcini Dec 10 '13 at 19:10