9

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

我想做的事?- 我想根据收到的通知执行一项操作,如下所示:

  1. 当应用程序打开并在前台即用户可见并且我收到通知时,我只需显示一个弹出窗口来启动我的 Activity B
  2. 当应用程序关闭时,即既不在后台也不在前台,我收到通知我将首先启动我的应用程序,然后启动 Activity B
  3. 当应用程序在后台运行但在最近运行但对用户不可见时,我想在不重新启动应用程序的情况下启动我的 Activity B。此外,在这种情况下,当用户按下 Activity B 时,他们应该在将其发送到后台之前看到他们离开的屏幕。

我做了什么?我已经达到了第 1 点和第 2 点。我想达到第 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;
}

然而,这在这两种情况下都返回 true,点 #2 和 #3,所以我无法仅区分 #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

4 回答 4

4

下面的代码对我有用

AndroidManifest.xml中

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:name=".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表示 -> 至少一个活动处于可见状态。

isApplicationVisible表示 -> 至少有一个活动已启动但未停止,表示应用程序处于运行状态

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

于 2015-06-10T19:08:17.610 回答
2

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

ActivityB如果不是案例 #1,则启动。在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...
于 2015-06-11T16:46:11.620 回答
1

我知道你想出了 1 和 2,但我自己的想法不对,以防你做了其他事情,你想看看。

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

    应该是正确的方式,如果它在前台然后通过eventbus发布事件, eventbus 是我的首选方式。

  2. 在具有堆栈的特定活动中启动应用程序? 用这个 答案看一下 TaskStackBuilder,它将提供如何正确执行此操作的信息。
  3. 在保留当前堆栈的同时恢复具有特定活动的应用程序?使用回调检查应用程序的状态,然后在收到通知时打开没有FLAG_ACTIVITY_NEW_TASK 的活动。这应该做 tricl。
于 2015-06-09T12:47:00.847 回答
1

如果您更改为不显示任何弹出窗口,只是为了始终转到 Activity B(已销毁、后台或前台),则不需要任何此检查。只是为了在您的通知上使用标志 FLAG_ACTIVITY_X(它是 GCM 这个通知?)。

清单上的 LaunchMode

意图标志

您可以使用 onNewIntent 方法检查意图是否来自通知并启动 Activity B。

通知适当的 BackStack

于 2015-06-10T12:28:34.253 回答