【问题标题】:Notification opens activity, press back button, prevent opening back stack activity?通知打开活动,按返回按钮,防止打开返回堆栈活动?
【发布时间】:2011-10-03 21:29:13
【问题描述】:

这看起来与my previous question 非常相似,因为它是某种跟进。我对给出的唯一解决方案不太满意;此外,解决方案是针对与此问题略有不同的问题。所以让我再试着解释一下这个问题......

  1. 在启动时会创建一个通知(带有BroadcastReceiver)。
  2. 我的应用程序主 Activity 已打开并按下主页按钮(该 Activity 将被发送到后台堆栈)。
  3. 我拉下状态栏并按下之前在启动时创建的通知。
  4. 这将启动一些与主要活动不同的活动。
  5. 我按下后退按钮并显示主要活动。

这与我之前的问题没有太大不同......问题是,“主要活动”只是一个例子。我本可以打开应用程序主活动,然后通过菜单选项打开关于活动并按下主页按钮。后台堆栈现在将是 MainActivity » AboutActivity。这意味着当在“一些活动”(通过按下通知开始)时按下返回按钮时,我们将被带到返回堆栈的顶部,即关于活动。

基本上想要的是防止当我在“某些活动”中按下后退按钮时打开任何其他活动(同样,通过按下通知开始)。我想被带到我所在的位置,可能是桌面或其他应用程序的活动,但不是我的应用程序的MainActivityAboutAcitivity,因为那不是我所在的位置,那些在后面的堆栈中,“睡觉”在背景。

我想出了一个解决方案,但我认为它不是很优雅,我正在寻找更优雅的东西......如果您有任何其他建议,请告诉我。

无论如何,这是我提出的解决方案:

// I use this class for public static (or public static final) members and
// methods

public final class AppHelper {
    public static final String KEY_RESUME_FROM_NOTIFICATION = "resumeFromNotification";

    private static boolean sResumeFromNotification = false;

    public static boolean getResumeFromNotification() {
        return sResumeFromNotification;
    }

    public static void setResumeFromNotification(boolean resumeFromNotification) {
        sResumeFromNotification = resumeFromNotification;
    }
}

public class MainActivity extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        (...)
    }

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

        if(AppHelper.getResumeFromNotification()) {
            AppHelper.setResumeFromNotification(false);
            moveTaskToBack(true);
        }
    }

}

public class AboutActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        (...)
    }

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

        if(AppHelper.getResumeFromNotification()) {
            AppHelper.setResumeFromNotification(false);
            moveTaskToBack(true);
        }
    }

}

public class SomeActivity extends Activity {

    // This will be called when the notification is pressed and the activity is
    // not opened yet

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        (...)

        extractIntentExtras(intent);
    }

    // This will be called if the activity is already opened and the
    // notification is pressed

    @Override
    protected void onNewIntent(Intent intent) {
        extractIntentExtras(intent);
        super.onNewIntent(intent);
    }

    private void extractIntentExtras(Intent intent) {
        Bundle bundleExtras = intent.getExtras();

        if(bundleExtras != null) {
            // These intent extras are set on the Intent that starts this activity
            // when the notification is pressed

            AppHelper.setResumeFromNotification(bundleExtras.getBoolean(
                AppHelper.KEY_RESUME_FROM_NOTIFICATION));

            mRowId = bundleExtras.getLong(AgendaNotesAdapter.KEY_ROW_ID);
            populateNoteUpdateFields();
        }
    }

}

我不知道,但这个解决方案对我来说看起来不是很优雅(但它可以按我的预期工作),我正在寻找替代方案或对我提出的解决方案作为可接受且良好的解决方案的强烈意见.想法?

【问题讨论】:

  • 您是否有任何用于活动的特殊标志? singleTop / singleInstance 或类似的东西?我没有看到你提到的活动,因为通知应该总是在新的任务堆栈中启动你的活动(它们需要 FLAG_ACTIVITY_NEW_TASK 标志)。
  • 我在MainActivity 上有singleTop(在清单中),没有别的。我总是对FLAG_ACTIVITY_NEW_TASK 标志感到困惑。无论是否设置了该标志,通知启动的活动都有效。我应该使用它还是不使用它?
  • 据我了解,应该始终为通知中的活动设置它。在您的情况下,您肯定希望设置它,因为您不希望通知活动成为正常任务堆栈的一部分。
  • 这也是我所理解的,但我没有看到任何不同的行为......:/
  • 这种方法对你有用吗? stackoverflow.com/questions/4628246/…

标签: android android-activity notifications android-intent back-button


【解决方案1】:

在做了更多阅读之后,也许这是您需要的标志组合:

Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);

我认为这应该会强制您的 SomeActivity 类在一个全新的任务中启动。

【讨论】:

  • 是的,这完全符合我的预期。好吧,实际上,它需要一个额外的标志才能更好地工作,即FLAG_ACTIVITY_SINGLE_TOP。只是这样当我打开一个通知然后打开另一个通知时,会重新加载活动而不是创建一个新的。由于documentation 中的所有粗体“警告”,我实际上从未尝试过多任务标志。我真的应该使用它吗?我没有实现顶级启动器...
  • FLAG_ACTIVITY_SINGLE_TOP 仅适用于您不想在 SomeActivity 已经在顶部打开的情况下。那是你想要的吗?另外,我认为您正在专门尝试创建一个与您的 Main 和 About 活动任务完全脱节的任务。使用 FLAG_ACTIVITY_MULTIPLE_TASK 是确保这种情况发生的唯一方法。
  • 是的,我现在意识到标志是确保我正在寻找的行为的唯一方法。我想我只是对有关该标志的文档警告有点“害怕”。
  • 是的.. 一个缺点是,如果用户离开它,他们将无法恢复他们的 SomeActivity 任务,但我想你已经考虑过了。实际上,您可能需要考虑 NO_HISTORY 标志,这样您就可以确定 SomeActivity 一旦用户离开它就完成了。
  • 是的,我确实考虑过。在这种特定情况下,恢复SomeActivity 毫无意义。为了清楚起见,您推荐NO_HISTORY 标志以及NEW_TASKMULTIPLE_TASK,正如您在回答中所建议的那样,对吧?
【解决方案2】:

从通知中启动 Activity 时,您可以控制将要打开的 Activity 如何放入后台堆栈,以及与 Intent 标志关联的任务。您可以尝试以下方法:

Intent intent = new Intent(mContext, SomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

如果这不起作用,请尝试设置一些 other flags,直到获得所需的行为。

【讨论】:

  • 没有标志可以完成这项工作...我已经尝试了许多它们和许多组合,但都没有解决问题。
  • 从您的启动活动中删除 singleTop。
  • 为什么?这究竟会做什么?
  • 它会让 FLAG_ACTIVITY_NEW_TASK 完成它的工作。
  • 你试过删除 singleTop 吗?
【解决方案3】:

您是否曾经希望您的 MainActivity 保留在历史记录中?如果不是,那么我简单粗暴的解决方案是在 MainActivity 暂停时完成它。 (在您的 MainActivity 中调用它)

@Override
public void onPause() {
    finish();
}

这将确保您的 MainActivity 在您离开时从历史记录中删除,并且在按下后退按钮时永远不会出现。 这也可以用于 AboutActivity。

【讨论】:

    猜你喜欢
    • 2011-03-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-07
    • 1970-01-01
    • 2015-01-27
    相关资源
    最近更新 更多