Android 将_重新排序到_前端时的困惑行为

Android 将_重新排序到_前端时的困惑行为,android,Android,活动A启动没有标志的活动B。堆栈现在为A-B,顶部为B。B开始活动A时,将标志\u activity\u REORDER\u TO\u FRONT(唯一的标志)。我希望堆栈现在是B-A。但是,当按下后退按钮时,它会返回主屏幕。在这里,我希望活动B被带到前面。再次单击启动器图标后,应用程序将打开,B作为正在运行的活动,堆栈中没有任何内容 启动模式是清单中的标准(默认) 这是预期的行为,而我只是没有正确地理解它 编辑:我创建了一个没有混杂因素的测试项目,但仍然看到了相同的行为。我只是不明白,它似乎不

活动A启动没有标志的活动B。堆栈现在为A-B,顶部为B。B开始活动A时,将标志\u activity\u REORDER\u TO\u FRONT(唯一的标志)。我希望堆栈现在是B-A。但是,当按下后退按钮时,它会返回主屏幕。在这里,我希望活动B被带到前面。再次单击启动器图标后,应用程序将打开,B作为正在运行的活动,堆栈中没有任何内容

启动模式是清单中的标准(默认)

这是预期的行为,而我只是没有正确地理解它

编辑:我创建了一个没有混杂因素的测试项目,但仍然看到了相同的行为。我只是不明白,它似乎不符合文档的要求

编辑:对我来说,这种行为似乎是框架中的一个BUG,请参阅下面我对答案的评论。我需要一个变通办法


}

公共类SecondActivity扩展了活动 { @凌驾 创建时受保护的void(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_秒); }

}

舱单:


首先,让我们从这句话开始吧

但是如果我的逻辑是正确的,那么当您将
重新排序到主
活动
(启动程序
活动
)时会发生什么情况呢?设置意图是为了使您返回到
启动程序

作为一个实验,尝试添加
活动
C,并尝试将
重新排序
B从C向前。 即:
A->B->C。。。A->C->B

如果顺序对您非常重要,您可能需要重写方法


我根本找不到这个问题

我刚刚重写了onFinish()方法,以检查哪些活动已关闭。


谷歌已经确认它是4.4.2上的一个bug,我也遇到了这个bug,并决定可能需要解决它。至少在我的例子中,似乎可以为4.4.2版提供定制的后堆栈实现。这一点也不漂亮,可能在所有情况下都不起作用,但它确实节省了我和我的
DrawerLayout
导航

首先,我有一个
NavigationDrawerActivity
,作为所有其他活动都扩展的类。在那里,我有一个静态
堆栈
,用于调用的类,以及一个可以从导航抽屉访问的类数组。
addClassToStack
方法是公共的,因此除抽屉外的其他导航方式也可以使用堆栈。请注意,要添加到堆栈中的类是如何首先被删除的(如果它存在的话),这样我们就可以获得与reorder to front标志通常提供的功能相同的功能。我已经用版本检查包围了黑客代码,因此黑客只在必要时使用

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        private Intent i;
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
            i = new Intent(NavDrawerActivity.this, activity_classes[pos]);
            addClassToStack(activity_classes[pos]);
            i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            nav_drawer.closeDrawers();
            startActivity(i);
        }
    }
解决方法的最后一部分是覆盖
onKeyDown
方法,如果在Android 4.4.2上按下了后退按钮(并且我们超出了导航中的第一个活动),那么要打开的活动将从我们的自定义后堆栈中获取并直接调用。请注意,堆栈中最上面的项始终是当前活动,因此我们需要去掉它,并将第二项用作目标。还要注意,每当返回到第一个活动时,我是如何清除正式任务历史记录的。这是必需的,因为否则,在再次按back并返回主屏幕后,下次访问应用程序时,它会直接进入官方后台堆栈的顶部

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;
        if (keyCode == KeyEvent.KEYCODE_BACK &&
            android.os.Build.VERSION.RELEASE.equals("4.4.2") &&
            classes.size() > 1) {
            classes.pop();
            Intent prev = new Intent(this, classes.peek());
            if (classes.size() == 1) {
                prev.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            } else {
                prev.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            }
            startActivity(prev);
            handled = true;
        }
        if (!handled) {
            return super.onKeyDown(keyCode, event);
        } else {
            return true;
        }
    }
}
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if ((intent.getFlags() | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) > 0) {
        mIsRestoredToTop  = true;
    }
}

@Override
public void finish() {
    super.finish();
    if (android.os.Build.VERSION.SDK_INT >= 19 && !isTaskRoot() && mIsRestoredToTop) {
        // 4.4.2 platform issues for FLAG_ACTIVITY_REORDER_TO_FRONT,
        // reordered activity back press will go to home unexpectly,
        // Workaround: move reordered activity current task to front when it's finished.
        ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        tasksManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
    }
}
剩下的唯一一件事(此处未显示)是将初始活动(应用程序启动时打开的活动)分别添加到后堆栈中的适当位置。在我的应用程序中,我有一个单独的开始屏幕,无法通过导航抽屉访问,因此我可以从该活动的onCreate调用
NavigationDrawerActivity.addClassToStack(StartScreenActivity.class)
。对于其他结构,您可以执行一些不同的操作,以确保初始活动仅作为第一项添加到堆栈中一次


现在,这是一个黑客,我还没有完全测试过,但它似乎在Nexus4(4.4.2)和NexusS(卡在4.1上)上也能工作。所以,如果你试图做这样的事情,但没有效果,不要生气,而是让我知道。:)

我找到了一个解决此错误的简单方法

覆盖Wintent和finish函数的任何可能重新排序到前台的活动,如下所示将是一个技巧,只是不完全测试,如果您发现此解决方法有任何问题,请通过ricotta与我联系。zhang@myriadgroup.com


我发现这个问题发生在S7 7.0操作系统上,当活动设置为Flag Intent.Flag_activity_REORDER_TO_FRONT且该活动自行完成时,用户将被带到设备的主屏幕

我为此添加的修复程序是-删除了Intent.flag\u ACTIVITY\u REORDER\u TO\u FRONT的标志,并添加了noHistory=true


通过这种方式,活动的新实例被推送到堆栈中,由于noHistory为true,已经是堆栈一部分的旧实例将被销毁。

请发布您的清单好吗?请发布您的主题呈现(意图)并不能解决问题,行为仍然相同。作为一个实验,尝试添加活动C并尝试将B从C重新排序到前面。即:A->B->C。。。A->C->B“这就像预期的那样工作。同样,如果你让活动C将A重新排序到前面(因此B-C-A),此时按活动A中的“后退”按钮将按预期返回到C,而不是启动程序。我只能猜测,我最初给出的两个活动示例中的行为是框架中的一个错误!什么版本?到目前为止,我只在4.4.2上进行了测试。我想这可能是特定于版本的事件。请检查您设备上的示例我检查了android-19,即android 4.4 Kitkat。尝试了你的项目,显然是个bug
@Override
protected void onNewIntent(Intent intent) {
}
public class NavigationDrawerActivity extends Activity {
    ...
    private static Stack<Class<?>> classes = new Stack<Class<?>>();
    private Class<?>[] activity_classes;
    ...
    public static void addClassToStack(Class<?> to_add) {
        if (android.os.Build.VERSION.RELEASE.equals("4.4.2")) {
            classes.remove(to_add);
            classes.push(to_add);
        }
    }
    ...
    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        private Intent i;
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
            i = new Intent(NavDrawerActivity.this, activity_classes[pos]);
            addClassToStack(activity_classes[pos]);
            i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            nav_drawer.closeDrawers();
            startActivity(i);
        }
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;
        if (keyCode == KeyEvent.KEYCODE_BACK &&
            android.os.Build.VERSION.RELEASE.equals("4.4.2") &&
            classes.size() > 1) {
            classes.pop();
            Intent prev = new Intent(this, classes.peek());
            if (classes.size() == 1) {
                prev.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            } else {
                prev.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            }
            startActivity(prev);
            handled = true;
        }
        if (!handled) {
            return super.onKeyDown(keyCode, event);
        } else {
            return true;
        }
    }
}
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if ((intent.getFlags() | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) > 0) {
        mIsRestoredToTop  = true;
    }
}

@Override
public void finish() {
    super.finish();
    if (android.os.Build.VERSION.SDK_INT >= 19 && !isTaskRoot() && mIsRestoredToTop) {
        // 4.4.2 platform issues for FLAG_ACTIVITY_REORDER_TO_FRONT,
        // reordered activity back press will go to home unexpectly,
        // Workaround: move reordered activity current task to front when it's finished.
        ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        tasksManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_NO_USER_ACTION);
    }
}