履歴スタック全体をクリアし、Androidで新しいアクティビティを開始します


332

スタックでアクティビティを開始し、その前に履歴全体をクリアすることは可能ですか?

状況

A-> B-> CまたはB-> Cのいずれかのアクティビティスタックがあります(画面Aはユーザートークンを選択しますが、多くのユーザーは単一のトークンしか持っていません)。

画面Cでは、ユーザー画面Bを無効にするアクションを実行する可能性があるため、アプリケーションは、画面Bがすでにスタックにあるかどうかに関係なく、画面Aに移動したいと考えています。これで、画面Aがアプリケーションのスタック上の唯一の項目になります。

ノート

他にも多くの同様の質問がありますが、この正確な質問に答えるものは見つかりませんでした。私は呼び出してみましたgetParent().finish()-これは常にnullポインタ例外になります。FLAG_ACTIVITY_CLEAR_TOPアクティビティが既にスタックにある場合にのみ機能します。

回答:


658

APIレベル11では、このために新しいインテントフラグが追加されました:Intent.FLAG_ACTIVITY_CLEAR_TASK

明確にするために、これを使用してください:

ジャワ

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

コトリン

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

残念ながら、API lvl <= 10の場合、これに対する明確な解決策はまだ見つかりません。「DontHackAndroidLikeThis」ソリューションは、確かに純粋なハックです。あなたはそれをすべきではありません。:)

編集: @ ベンピアソンのコメントによると、API <= 10の場合、IntentCompatを使用できます場合、同じクラスをました。IntentCompat.FLAG_ACTIVITY_CLEAR_TASKフラグを使用してタスクをクリアできます。したがって、APIレベル11以前もサポートできます。


23
明確にするために、これを使用してください:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
user123321

2
Intent.FLAG_ACTIVITY_NEW_TASKがないと、アプリがandroid 4で終了することがあります
max4ever

22
-あなたは、事前APIレベル11をサポートできるようIntentCompatは、同様に今明確なタスクにフラグを持っているdeveloper.android.com/reference/android/support/v4/content/...
ベン・ピアソン

10
IntentCompat.FLAG_ACTIVITY_CLEAR_TASKは、APIレベル<10を備えたデバイスでは無視されdeveloper.android.com/reference/android/support/v4/content/...
デヴィッド・

7
IntentCompatのフラグはクラッシュを回避するためだけのものですが、@ Davidが言うように何もしません。
Sloy、2014

49

ケース1:2つのアクティビティAとBのみ:

ここでのアクティビティフローはA-> Bです。Bから[戻る]ボタンをクリックすると、アプリケーションを閉じる必要があります。AからアクティビティBを開始するときに、finish()を呼び出すだけで、アクティビティAがアクティビティAをBackstack.egに格納するのを防ぐことができます。アプリケーションの表示/スプラッシュ画面。

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

ケース2:3つ以上の活動:

A-> B-> C-> D-> Bのようなフローがあり、アクティビティDからのアクティビティ中にアクティビティBで戻るボタンをクリックした場合。

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

ここでは、Intent.FLAG_ACTIVITY_CLEAR_TOPとIntent.FLAG_ACTIVITY_NEW_TASKによってスタックがクリアされ、一番上のスタックになるため、アクティビティBは新しいインスタンスではなくバックスタックから開始されます。したがって、[戻る]ボタンを押すと、アプリケーション全体が終了します。


2
これでうまくいきました。私はこれらのフラグをすべてのアクティビティに入れました。これらのアクティビティでは、戻るボタンは前のアクティビティに完全に移動し、メインアクティビティではIntent intent = new Intent(Intent.ACTION_MAIN);を使用します。intent.addCategory(Intent.CATEGORY_HOME); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); アプリ全体が閉じられ、メモリには残っていますがアクティブではありません。再起動すると、アプリはスプラッシュスクリーンに移動します:)
Rako

これが最良の答えです。誰かが私と同じシナリオを持っている場合:A-> B-> C-> D-> E->(B)From E-> Bは結果を持つはずです:A-> B
Shem Alexis Chavez

39

Androidの新しいバージョン> = API 16を使用 finishAffinity()

アプローチはAPI 16以上に適しています。

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • 新しいアクティビティを開始するのと同じで、すべてのスタックをクリアします。
  • またはMainActivity / FirstActivityを再起動します。

1
これはトリックでした、フラグは私のために4.xxで動作しませんでした、そしてこれは完全に機能しました!ありがとう
Jonathan Aste

1
現在のアクティビティを含む以下のすべてのアクティビティを完了し、自分のタスクで新しいアクティビティを開始することが目標である場合、これは正しい答えのようです。
ToBe 2018

24

私もこれに数時間を費やしました...そしてFLAG_ACTIVITY_CLEAR_TOPはあなたが望むように聞こえることに同意します:起動されているアクティビティを除いてスタック全体をクリアし、[戻る]ボタンがアプリケーションを終了します。ただし、Mike Repassが述べたように、FLAG_ACTIVITY_CLEAR_TOPは、起動しているアクティビティがすでにスタックにある場合にのみ機能します。アクティビティが存在しない場合、フラグは何もしません。

何をすべきか?FLAG_ACTIVITY_NEW_TASKを使用して、起動中のアクティビティをスタックに入れます。これにより、そのアクティビティが履歴スタックの新しいタスクの開始になります。次に、FLAG_ACTIVITY_CLEAR_TOPフラグを追加します。

これで、FLAG_ACTIVITY_CLEAR_TOPがスタック内の新しいアクティビティを見つけに行くと、そこにあり、他のすべてがクリアされる前にプルアップされます。

これが私のログアウト関数です。Viewパラメータは、関数が関連付けられているボタンです。

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}

1
CLEAR_TOPではなくCLEAR_TASKですか?
アンディ

14

スタックを変更しないでください。Androidの戻るボタンは、Webブラウザーと同じように機能します。

私はそれを行う方法を考えることができますが、それはかなりハックです。

  • 例にsingleTask追加してアクティビティを作成しますAndroidManifest

    <activity android:name=".activities.A"
              android:label="@string/A_title"
              android:launchMode="singleTask"/>
    
    <activity android:name=".activities.B"
              android:label="@string/B_title"
              android:launchMode="singleTask"/>
  • Applicationどこに行くかというロジックを保持する拡張。

例:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.push(activity);
  }
}

AからBへ:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);

BからCへ:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);

C:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}

pop()スタックから戻るボタンを処理します。

もう一度、これを行うべきではありません:)


最後に、スタックをそのままにして、現在の画面が無効であることをユーザーに伝えることにしました
Casebash

1
Androidではこの方法でアクティビティスタックを管理できないので、非常にイライラします。私は将来のAndroidアプリでこのソリューションを使用したくなります。
Cephron 2013

4
なぜこれが使用されるべきではないのかを明確にするために:これはメモリリークを作成する良い方法です。ある時点で、OSはバックグラウンドアクティビティをApplication強制終了する場合がありますが、インスタンスを取得するため、OSは破棄されたアクティビティから残っているRAMを解放できなくなります。
Vit Khudenko 2013年

@Arhimed他に問題はありますか?弱い参照のみを保持することで、メモリリークを修正できます。
Navin、2014

1
@Navinはい、リークは弱い参照で回避できますが、GCの後にライブのアクティビティ参照がない場合、アプローチ全体が役に立たなくなります。繰り返しますが、これを行わないでください。これは、Androidの間違ったアプローチです。
Vit Khudenko 2014

12

新しいアクティビティを開始した直後に、を使用して、現在のアクティビティが新しいアクティビティの後ろにスタックされないようにstartActivity呼び出しますfinish()


+1特定の状況で1つのアクティビティのみが履歴スタックに入れられるのを防ぐための素晴らしいソリューション。
marsbear 2012

27
あなたがフィニッシュしたばかり....他の人を前のアクティビティをクリアしませんが、スタック内に複数のアクティビティがある場合は動作しません
Necronet

5

これを試して:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();

4

高度な再利用可能なKotlin:

setterメソッドを使用してフラグを直接設定できます。Kotlinでorある代替のJavaビット単位のためか|

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

これを定期的に使用する場合は、Intent拡張関数を作成します

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

その後、インテントを開始する前にこの関数を直接呼び出すことができます

intent.clearStack()

他の状況でフラグを追加するオプションが必要な場合は、オプションのパラメーターを拡張関数に追加します。

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

2
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

2

以下のコードを試してください、

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

このように使用している場合、もう一度更新してAPIを呼び出しますが、以前に存在していたすべてのstatckがクリアされます
Harsha

2

私にとって、上記の方法どれも機能しませ

これを実行して、以前のすべてのアクティビティクリアします

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)

-1

場合によっては、AndroidエミュレーターがEclipse DDMSツールに接続できず、adbを手動で開始するように要求することがあります。その場合、コマンドプロンプトを使用してadbを起動または停止できます。


1
場合によっては、AndroidエミュレーターがEclipse DDMSツールに接続できず、adbを手動で開始するように要求することがあります。その場合、コマンドプロンプトを使用してadbを起動または停止できます。Intent i = new Intent(OldActivity.this、NewActivity.class); //新しいタスクを設定してフラグをクリアするi.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)startActivity(i);
RajeshkumarG 2016年

-2

私はあまりにも単純なハックを見つけましたこれは次のように新しい要素を追加するだけです AndroidManifest:-

<activity android:name=".activityName"
          android:label="@string/app_name"
          android:noHistory="true"/>

これによりandroid:noHistory、スタックから不要なアクティビティがクリアされます。


2
このアクティビティで許可を求める場合、Android 6.0以降でこのアプローチにより問題が発生する可能性があります。
Vitaliy A
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.