履歴スタックからのアクティビティの削除


382

私のアプリは、ユーザーが初めてアプリを実行したときに、次のようなサインアップアクティビティを表示します。

  1. ActivitySplashScreen(ゲームへようこそ、アカウントにサインアップしますか?)
  2. ActivitySplashScreenSignUp(素晴らしい、この情報を記入してください)
  3. ActivityGameMain(メインゲーム画面)

そのため、ユーザーが各画面のボタンをクリックすると、アクティビティはその順序で互いに起動します。

ユーザーがアクティビティ#2から#3に移動したときに、履歴スタックから#1と#2を完全に消去できますか?ユーザーが#3にいて、戻るボタンを押すと、スプラッシュ画面に戻るのではなく、ホーム画面に移動するようにしたいと思います。

タスクでこれを達成できると思います(つまり、#3で新しいタスクを開始する)が、もっと簡単な方法があるかどうかを確認したかったのですが、

ありがとう


ホーム画面に入った後、ユーザーがアプリを再開すると、ActivitySplashScreenまたはActivityGameMainに移動しますか?
タミル語

回答:


632

これは、ファイルの関連エントリでandroid:noHistory 属性"true"に設定することで実現できます。例えば:<activity>AndroidManifest.xml

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />

12
これはそれを行うための最良の方法です。
shkschneider 2012

22
同等に使用できますFLAG_ACTIVITY_NO_HISTORY
Timmmm 2012年

34
コードからこれをどのように達成できますか?ずっとやりたくないから。特定の状況でのみ、特定のアクティビティを履歴から削除したいと思います。
Namratha 2013年

8
noHistory属性を使用するとそのアクティビティが終了するため、たとえばG +ログインで予期しない動作が発生する可能性があることに注意してください。参照:stackoverflow.com/questions/20383878/…私のアプリがトレースなしでクラッシュし続けたため、このバグを見つけるのにしばらくかかりました。
アカプルコ

13
必要なフラグはリンクであるため、コピーするのは難しいため、ここでは簡単にコピーできるフラグを指定します。android:noHistory="true"
MirroredFate 2015

137

転送を使用して、次のアクティビティを起動しながら、アクティビティスタックから前のアクティビティを削除できます。 これの例はAPIDemosにありますが、基本的にはを呼び出したfinish()直後に呼び出すだけstartActivity()です。


1
こんにちはダニエル、例を読みましたが、履歴スタックは1アクティビティ分しかクリアされませんよね。スタックがA、Bのように見え、Cを起動している場合は、Cを新しいルートにして、AとBを完全にクリアします。sdkの例では、Bからfinish()を呼び出すと、Aのスタックが残ります。 、Cさん、そうではないでしょうか。ありがとう。
マーク

1
Bを起動するときにAをクリアし、Cを起動するときにBをクリアすることができます。ただし、そうしたい場合は、BからAにバックアウトできないと思います。それが問題であるなら、私はこれについてもっと考えなければならないでしょう。
Dan Lew

3
マーク、あなたが望むものを達成するために、あなたはフラグを使う必要があります:FLAG_ACTIVITY_CLEAR_TOP。お役に立てば幸いです。
フランシスコジュニア

3
FLAG_ACTIVITY_CLEAR_TOPCはまだバックスタックにないため、機能しません。
Timmmm 2012年

1
@DanielLew APIDemosには非常に多くの例があります。あなたは提案された例の名前を持っているでしょうか?
ステファン2015

52

46
これは、起動するアクティビティの履歴を設定しないことに注意してください。起動するアクティビティの履歴がないようandroid:noHistory="true"に、マニフェストに設定するだけです。
georgiecasey 2012年

1
これはうまくいきます。intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)このフラグを設定するには、を使用します。
vovahost

1
@georgiecaseyこれは、履歴に残したい場合や、履歴に残したくない場合に便利です。
Vihaan Verma

24

これはおそらく理想的な方法ではありません。誰かがより良い方法を持っているなら、私はそれを実装するのを楽しみにしています。これが、バージョン11より前のSDKでこの特定のタスク実行する方法です。

時間が空いたときに離れたいクラスごとに、これを行う必要があります。

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

次に、スタックからポップのチェーンをオフに設定する必要があるものは、開始したいときにこれを呼び出す必要があります。

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

その後、活動はスタックにありません!
アクティビティを開始し、その背後でクリーンアップを開始できることを覚えておいてください。実行は単一の(ui)スレッドに従っていません。


後で誰かがこれに遭遇した場合に知っておくことが重要だと思うかもしれません。画面を回転させた場合、スタックから最後のアクティビティをポップすると、Androidがアプリケーションを再起動してくれます。これに注意してください!
Travis

あなただけのユーザーが次のアクティビティ+1で何をするかに応じて、条件付きスタックから活動を削除したい場合、これは良い答えです
theMothaShip

23

API 11より前に機能する1つの方法は、ActivityGameMain最初に開始し、次にonCreateそのアクティビティの中でアクティビティを開始するActivitySplashScreenことです。ActivityGameMainあなたはスプラッシュのためにあまりにも早くstartActivityを呼び出しとして表示されません。

次に、インテントにこれらのフラグを設定して、開始時にスタッククリアできますActivityGameMain

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

これをActivitySplashScreenに追加する必要もあります。

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

そのため、そのアクティビティを押し戻しても、には戻りませんActivityGameMain

私はあなたがスプラッシュスクリーンをどちらにも戻さないことを望んでいると思います、これを達成するためnoHistoryにあなたのでそれを設定することをお勧めしますAndroidManifest.xml。次に、goBackPressedコードをActivitySplashScreenSignUpクラスに配置します。

しかし、私はこれを破るいくつかの方法を見つけました。ActivitySplashScreenSignUpが表示されているときに通知から別のアプリを起動します。バック履歴はリセットされません。

これを回避する唯一の方法は、API 11です。

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

私はこのように使用します。

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

ありがとう。メニューに[ホーム]ボタンがあり、ユーザーがそこから家をクリックしたときにスタックされたアクティビティが表示されないようにしたい場合に、これは役に立ちました。
ghitesh

8

私はこれに遅れていることを知っています(質問を聞いてから2年が経過しています)が、戻るボタンの押下を遮断することでこれを達成しました。特定のアクティビティをチェックするのではなく、カウントを確認します。カウントが3未満の場合は、アプリを背面に送ります(アプリを一時停止し、ユーザーを起動前に実行していたものに戻します)。導入画面が1つしかないので、3つ未満をチェックします。また、アプリでユーザーがメニューからホーム画面に戻ることができるため、カウントを確認します。これにより、スタックにイントロ画面以外のアクティビティがある場合、通常のように他の画面に戻ることができます。

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

7

マニフェストでは、次を追加できます。

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

あなたも呼び出すことができます

finish()

startActivity(..)を呼び出した直後


2
マニフェストに物を置くよりも活動フラグを使用する方が良いです。
Trevor Hart


4

誰もこのエレガントなソリューションについて言及していないのはおかしいです。これは受け入れられる答えになるはずです。

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

ここで重要なのはintent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 、仲介者として使用することですActivity。その中間のリンクが壊れるDashActivityと、スタックの最初と最後の意志。

android:noHistory="true"Activityコールバックとして使用すると問題が発生するため、これは不適切なソリューションonActivityResultです。これは推奨されるソリューションであり、受け入れる必要があります。


1
その旗は本当であるにはあまりにも良さそうに聞こえた。FLAG_ACTIVITY_NO_HISTORYは適切に機能し、スタックの一番上にフラグが設定されたアクティビティがある間に、アプリをバックグラウンドにしてから再びフォアグラウンドにするまでは、予想どおりに機能します。バックグラウンドに移動すると、アクティビティは破棄されます。アプリに戻ると、スタックから前のアクティビティが表示されます。私は間違いなくそのような行動を望んでいませんでした。
NeverwinterMoon 2018年

4

手遅れですが、お役に立てば幸いです。答えのほとんどは正しい方向を指していない。そのようなことのための2つの単純なフラグがあります。

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Androidドキュメントから:

public static final int FLAG_ACTIVITY_CLEAR_TASKがAPIレベル11で追加されました

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

アクティビティが開始される前にクリアされるアクティビティ。つまり、アクティビティは空のタスクの新しいルートになり、古いアクティビティはすべて終了します。これは、FLAG_ACTIVITY_NEW_TASKと組み合わせてのみ使用できます。


1

このようにstartActivity(intent)の前にthis.finish()を呼び出すだけです-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

「this」にエラーがあるユーザーは、「ActivityOne.this」に変更する必要があります
ninbit

1

履歴からアクティビティを削除するには、不要なアクティビティの前にフラグを設定します

A-> B-> C-> D

BとCをクリアしてフラグを設定する場合は、A、B、C、Dが4つのアクティビティであると仮定します。

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

アクティビティAおよびB

これがコードビットです

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.