Android 什么';在不更改清单中的启动模式的情况下,将现有任务清除到顶部的最佳方法是什么?

Android 什么';在不更改清单中的启动模式的情况下,将现有任务清除到顶部的最佳方法是什么?,android,Android,我正在开发一个开源应用程序,以下是我在启动根活动时的要求: 应用程序需要始终是单个任务,以防止通过某些共享数据发生无效状态 当通过启动意图启动时,用户应返回到任何先前任务顶部的活动 当通过ACTION_VIEW(例如,通过file manager)启动时,应将用户带到根活动,清除所有以前的历史记录,并通过导入文件正确处理意图 显然,在清单中使用android:launchMode=“singleTask”时需要2,我无法控制外部意图中包含哪些标志 如果,我可以通过完成活动来处理要求1和2!isT

我正在开发一个开源应用程序,以下是我在启动根活动时的要求:

  • 应用程序需要始终是单个任务,以防止通过某些共享数据发生无效状态

  • 当通过启动意图启动时,用户应返回到任何先前任务顶部的活动

  • 当通过ACTION_VIEW(例如,通过file manager)启动时,应将用户带到根活动,清除所有以前的历史记录,并通过导入文件正确处理意图

  • 显然,在清单中使用android:launchMode=“singleTask”时需要2,我无法控制外部意图中包含哪些标志

    如果
    ,我可以通过完成活动来处理要求1和2!isTaskRoot()
    。处理要求3更为棘手;在经历了多次冲突之后,我发现重新启动意图,加入flag
    flag\u ACTIVITY\u CLEAR\u TOP
    这类功能很有效,但需要注意的是
    isTaskRoot()
    ,因此我不得不引入一个黑客程序,看看该活动是否很快就会成为root,否则应用程序会在继续之前冻结几秒钟

    无论如何,这是代码;任何满足所有要求的不太老套的解决方案都将受到欢迎

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Intent intent = getIntent();
        if (!isTaskRoot() && 
            (intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_TOP) == 0) {
            // App freezes for a while without hack in second condition above
            super.onCreate();
            Intent reloadIntent = new Intent(RootActivity.this, RootActivity.class);
            if (intent.getExtras() != null) {
                reloadIntent.putExtras(intent.getExtras());
            }
            if (intent.getData() != null) {
                reloadIntent.setData(intent.getData());
            }            
            String action = intent.getAction();            
            switch (action) {
                case Intent.ACTION_VIEW:
                    // Go back to previous task & take user to root, clearing history
                    reloadIntent.setAction(intent.getAction());
                    reloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    finish();
                    startActivity(reloadIntent);
                    break;
                default :
                    // Go back to the top of previous task without clearing history
                    reloadIntent.setAction(Intent.ACTION_MAIN);
                    reloadIntent.addCategory(Intent.CATEGORY_LAUNCHER);
                    reloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    finish();
                    startActivityIfNeeded(reloadIntent, 0);
                    break;
            }
        } else {        
            // Normal onCreate() method for when launched as root
            // Import file specified by intent.getData().getEncodedPath()
        }
    }
    

    一个比问题中的黑客更好的解决方案是使用单独的活动作为意图的委托。以下是根据项目源代码逐字发布的最终解决方案:

    public class IntentHandler extends Activity {
        @Override 
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Intent intent = getIntent();
            Intent reloadIntent = new Intent(this, DeckPicker.class);
            reloadIntent.setDataAndType(intent.getData(), intent.getType());
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_VIEW)) {
                // This intent is used for opening apkg package
                // We want to go immediately to DeckPicker, clearing any history in the process
                // TODO: Still one bug, where if AnkiDroid is launched via ACTION_VIEW,
                // then subsequent ACTION_VIEW events bypass IntentHandler. Prob need to do something onResume() of AnkiActivity
                reloadIntent.setAction(action);
                reloadIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(reloadIntent);
                finish();
            } else {
                // Launcher intents should start DeckPicker if no other task exists,
                // otherwise go to previous task
                reloadIntent.setAction(Intent.ACTION_MAIN);
                reloadIntent.addCategory(Intent.CATEGORY_LAUNCHER);
                reloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivityIfNeeded(reloadIntent, 0);
                finish();
            }
        }
    }