Android应用,活动状态(正在运行,未运行,前景/背景)

时间:2015-06-02 10:36:31

标签: android android-activity activity-lifecycle android-task

我遇到了一项要求,但我无法获得正确的实施方式,因此需要您的帮助。

我想做什么? - 我想根据我得到的通知执行操作,如下所示:

  1. 当应用程序处于打开状态且处于前台状态时,即用户可见并且我收到通知我只是显示一个弹出窗口以启动我的活动B
  2. 当应用程序关闭时,即无论是在后台还是在前台,我都会收到通知,我将首先启动我的应用程序,然后启动活动B
  3. 当应用程序在后台运行但是在最近但用户看不到时,我想启动我的活动B而不重新启动应用程序。此外,在这种情况下,当用户按下活动B时,他们应该在将其发送到后台之前看到他们停止的屏幕。
  4. 我做了什么? 我已经取得了第一点和第二点。我想达到第3点。我试过下面的

    public static boolean isApplicationBroughtToBackground(final Activity activity) {
      ActivityManager activityManager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
      List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
    
      // Check the top Activity against the list of Activities contained in the Application's package.
      if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        try {
          PackageInfo pi = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_ACTIVITIES);
          for (ActivityInfo activityInfo : pi.activities) {
            if(topActivity.getClassName().equals(activityInfo.name)) {
              return false;
            }
          }
        } catch( PackageManager.NameNotFoundException e) {
          return false; // Never happens.
        }
      }
      return true;
    }
    

    然而,在两种情况下,#2和#3都会返回true,所以我无法区分#3。

    此外,我在每项活动中尝试了以下内容,

    @Override
    protected void onPause() {
        super.onPause();
        saveIsPausedInPref(true);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        saveIsPausedInPref(false);
    }   
    

    但是,如果通过按主页按钮将应用程序发送到后台,它也不能提供所需的结果我的首选项将 isPaused = true 并且如果用户从最近删除应用程序然后它将保持正确,并且当通知到达时我将无法区分第2点和第3点。

    为整个故事道歉,但我希望我能够解释我的要求。

    提前致谢。 :)

    编辑:

            <activity
                android:name=".HomeActivity"
                android:screenOrientation="portrait" >
            </activity>
            <activity
                android:name=".ChatProfileActivity"
                android:screenOrientation="portrait" >
            </activity>
    

4 个答案:

答案 0 :(得分:4)

下面的代码适用于我

AndroidManifest.xml

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:name=".MyApplication"
            >

<强> MyApplication.java

public class MyApplication extends Application {
private ActivityLifecycleCallbacks myLifecycleHandler;

@Override
    public void onCreate() {
        super.onCreate();
        myLifecycleHandler=new MyLifecycleHandler();
        registerActivityLifecycleCallbacks(myLifecycleHandler);
    }
}

<强> MyLifecycleHandler.java

public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    private static final String TAG = MyLifecycleHandler.class.getSimpleName();

private static int resumed;
private static int paused;
private static int started;
private static 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;
    Log.d(TAG, "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;
    Log.d(TAG, "application is visible: " + (started > stopped));
}

public static boolean isApplicationVisible() {
    return started > stopped;
}

public static boolean isApplicationInForeground() {
    return resumed > paused;
}
}

现在使用 myLifecycleHandler 方法,您可以获得所需的所有州。

isApplicationInForeground 表示 - &gt;至少一项活动处于可见状态。

isApplicationVisible 表示 - &gt;至少有一个活动已经开始但没有停止,意味着应用程序正在运行状态

如果 isApplicationInForeground 为true isApplicationVisible 将始终为true,反之亦然

答案 1 :(得分:2)

要区分案例#2和案例#3,您可以执行以下操作:

如果不是#1,请启动ActivityB。在ActivityB.onCreate()执行此操作:

super.onCreate(...);
if (isTaskRoot()) {
    // ActivityB has been started when the app is not running,
    //  start the app from the beginning
    Intent restartIntent = new Intent(this, MyRootActivity.class);
    startActivity(restartIntent);
    finish();
    return;
}
... rest of onCreate() code here...

答案 2 :(得分:1)

我知道你弄明白了1&amp; 2但是,如果你做了别的事情你想看看,我的自己很难对付。

  1. 如何知道您的应用是否在前台?

    this 应该是正确的方法,如果它在前景然后发布一个事件 通过eventbus,eventbus是 我喜欢的方式。

  2. 使用堆栈在特定活动中启动应用程序? 看一眼 TaskStackBuilder 有了这个 answer, 它将提供如何正确的信息。
  3. 在保留当前堆栈的同时恢复具有特定活动的应用? 使用回调检查应用程序的状态,然后在收到通知时打开活动,不用 FLAG_ACTIVITY_NEW_TASK。这应该是tricl。

答案 3 :(得分:1)

如果您更改为不显示任何弹出窗口,只需要始终转到活动B(已销毁,背景或前景),您就不需要任何此检查。 只是在您的通知上使用标志FLAG_ACTIVITY_X(这是GCM的通知吗?)。

LaunchMode on Manifest

Intent Flags

如果来自通知并启动活动B,您可以使用onNewIntent方法检查意图。

Notification Proper BackStack