web-dev-qa-db-ja.com

履歴スタックからアクティビティを削除する

私のアプリは、ユーザーが初めてアプリを実行したときに登録アクティビティを表示します。

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

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

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

私はタスクでこれを達成することができると思う(すなわち#3で新しいタスクを始める)が、もっと簡単な方法があるかどうかを見たかった

ありがとう

365
Mark

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

<activity
    Android:name=".AnyActivity"
    Android:noHistory="true" />
607
Aitor Gómez

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

134
Daniel Lew

はい、 Intent.FLAG_ACTIVITY_NO_HISTORY をご覧ください。

50
Matthias

これはおそらく理想的な方法ではありません。誰かがもっと良い方法を持っているなら、私はそれを実行するのを楽しみにしています。これはIがバージョン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)スレッドに続かない。

23
Travis

API 11より前のバージョンでは、最初にActivityGameMainを起動し、次にそのActivityのonCreateActivitySplashScreenアクティビティを起動します。スプラッシュのためにstartActivityを呼び出してもActivityGameMainは表示されません。

それであなたはActivityGameMainを起動するときにIntentでこれらのフラグをセットすることでスタックをクリアすることができます

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

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

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

だからその活動を押し戻してもあなたのActivityGameMainには戻りません。

スプラッシュスクリーンを元の状態に戻したくない場合は、これを実現するために、AndroidManifest.xmlnoHistoryに設定することをお勧めします。それから、goBackPressedコードを代わりにActivitySplashScreenSignUpクラスに入れてください。

しかし、これを打破する方法がいくつかあります。 ActivitySplashScreenSignUpが表示され、過去の履歴がリセットされていないときに、通知から別のアプリを起動します。

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

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
21
mxcl

私はこの方法を使います。

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

私はこれが遅れていることを知っています(質問が出されてから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();
    }
}
8
alphonzo79

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

Android:noHistory="true"

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

電話することもできます

finish()

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

6
Anubhav

noHistory="true"Manifestファイルに設定するだけです。バックスタックからアクティビティが削除されます。

aPI> = 15からAPI 23の場合、他の解決策はうまくいきません。やっと私はこれを手に入れた。

 Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
 nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
 startActivity(nextScreen);
 ActivityCompat.finishAffinity(currentActivity.this);
3
Kamal Bunkar

誰もこのエレガントな解決策について言及していないのはおかしいです。これは受け入れられた答えであるはずです。

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();
}

ここで重要なのは、仲介者Activityname__にintent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);を使用することです。その中間のリンクが壊れたら、DashActivityname__がスタックの最初と最後になります。

Android:noHistory="true"は、Activityname__をコールバックとして使用する場合に問題を引き起こすため、悪い解決策です。例えばonActivityResultname__。これは推奨される解決策であり受け入れられるべきです。

3
Rowland Mtetezi

手遅れですが、助けになれば幸いです。答えのほとんどは正しい方向を指していません。そのようなことには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と組み合わせてのみ使用できます。

3
Nouman Ghaffar

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

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