アクティビティがアプリケーションのアクティビティスタックの最後のアクティビティかどうかを確認するにはどうすればよいですか?


122

ユーザーが現在のアクティビティを終了した場合にホーム画面に戻るかどうかを知りたい。


1
これは役立つかもしれません:stackoverflow.com/questions/2590581/activities-stack
bigstones

43
アクティビティにisTaskRootと呼ばれる関数があることがわかりました。これはあなたの助けになると思います。
H9kDroid

回答:


116

更新(2015年7月):

以来getRunningTasks() API 21からそれが続く方が良いでしょう、非推奨の取得raukodraugの 答えエド・バーネット 1を(私は二番目を好むだろう)。


ActivityManager を使用して、現在のタスクとそのスタックをチェックする可能性があります。

したがって、アクティビティが最後のものかどうかを判断するには、次のようにします。

  • マニフェストでandroid.permission.GET_TASKS権限をリクエストします。
  • 次のコードを使用します。

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }

上記のコードは、単一のタスクがある場合にのみ有効であることに注意してください。アプリケーションにタスクの数が存在する可能性がある場合-他のtaskList要素を確認する必要があります。タスクについてもっと読むタスクとバックスタック



25
H9kDroidは正しい提案をしました。選択された答えはハックです。isTaskRoot()メソッドを使用して正しい方法で行う必要があります。
スーフィアン2014

@Sufian特にハックはどこですか?コードは論理的であり、意図された方法でオープンAndroid APIを使用します(たとえば、実行中のタスクを取得するにはgetRunningTasksを使用する必要があり、これらのタスクを分析する目的でのみ呼び出したい場合があります)。get(0)の使用法は十分に文書化され、論理的です。「現在実行中のタスクのリストを返します。最新のものから順に、古いものから順に返します」。
sandrstar '29年

2
getRunningTasksは()APIレベル21に廃止され
gilchris

フラグメントに対して同じことをできますか?はいの場合、どのように?助けてください
Sagar Devanga

1
@ Mr.Drewが@ raukodraugからの最高投票数の回答を見る
David Wasser

167

@ H9kDroidのコメントを、同様の質問をする人のための最良の回答として投稿します。

isTaskRoot()を使用して、アクティビティがタスクのルートであるかどうかを確認できます。

これが役に立てば幸い


1
isTaskRootの使用方法が明確になるように、1行のコードを入力してください。ありがとう。
Kaveesh Kanwal 2015年

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
唯一の問題は、<= 4.4では>> 5.xとは異なる動作をすることです。常にfalseを返すようです。
chubbsondubs 2016

コメントで提供されているサンプルコードを回答に組み込むことを検討して、将来の読者が簡単に扱えるようにする必要があると思います。
Isac、

すばらしい答え。私の場合、ユーザーが通知をクリックした後、ユーザーが以前にアプリケーションを閉じた場合、そのアクティビティはルートである可能性があります
dave o grady

19

これが新しい初心者に役立つことを願っています。上でうまくいく答えに基づいて、私はコードスニペットも共有しているので、簡単に実装できます。

解決策:私は使用isTaskRoot()返された、真の場合、現在の活動は、あなたのスタック内の活動であれば、私はまた、内ケースを扱うよりも、他の私が代わりに新しい開くスタックに最後の活動にスタック行く中に、いくつかの活性を有するカスタム1を。

あなたの活動で

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }


5

これを達成する方法があるかもしれませんが(他の回答を参照)、私はあなたがそれを行うべきではないことをお勧めします。通常のAndroidアプリケーションは、ホーム画面が表示されるかどうかを知る必要はありません。

データを保存しようとしている場合は、データ保存コードをonPause()メソッドに配置します。ユーザーに既存のアプリケーションについての考えを変える方法を提供しようとしている場合は、Backキーのキーのアップ/ダウンとonBackPressed()メソッドをインターセプトして、「Are you sure?」促す。


1
ユーザーがアクティビティを離れない限り、サービスを実行する必要がある場合はどうですか?onStopのような関数は、画面をオフにした後に呼び出すことができるため、トラップできません。
マイケル

2
バックグラウンドサービスがアクティビティを起動する場合、おそらくそれがスタック上の唯一のアクティビティであるかどうかを知りたいでしょう。
マットW

4

これを追跡する1つの方法は、新しいアクティビティを開始するときにマーカーを含め、マーカーが存在するかどうかを確認することです。

新しいアクティビティを開始するたびに、マーカーを挿入します。

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

そして、あなたはこのようにそれをチェックすることができます:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
アクティビティが強制終了され、アクティビティスタックが再構築された場合は機能しません-要求に応じて各アクティビティ。
AlikElzin-kilaka 2013

3

を使用したsandrstarのソリューションの問題ActivityManagerは、この方法でタスクを取得するための権限が必要です。私はより良い方法を見つけました:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

Activityスタックの底に他の活動はそれを得るべきではないながら、オールウェイズは、デフォルトでは、このカテゴリを取得する必要があります。
ただし、一部のデバイスでこれが失敗した場合でも、起動時に設定できますActivity

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

アクティビティがプッシュ通知から開かれた場合はどうなりますか?
カテゴリランチャー

私の回答の2番目の部分がまだ当てはまると確信しています。カテゴリをインテントのヒントとして設定できます。この場合、おそらくあなたの通知コンテキストの意図にあります。それ以外に、フラグを使用することもできます。:意図して、通知の作成には、このリンクを参照してくださいstackoverflow.com/questions/13716723/...
A. Binzxxxxxx

それでも、最も古いアクティビティがMainActivityで、現在は再開されている場合、プッシュ通知を受け取り、pendingIntentをCATEGORY_LAUNCHERで開くように設定すると、このカテゴリのアクティビティが2つあります。おそらく別のタスクで
nbtk

通知でどのように機能するかは正確にはわかりません。私はあなたがそれをここで行うようにそれらを使用したことはありません。このアプローチでそれを行う簡単な方法があると確信していますが、2014年の第1四半期以来、Androidコードには触れていません。この場合は、2番目のカテゴリを使用しますか?またはいくつかのフラグ?しかし、私はそのように機能するその考えを推測します。メインアクティビティを開始して、正しいアクティビティを開くためのメタ情報を追加してみませんか?
A. Binzxxxxxx 2017

2

AppCompatActivityを拡張して、すべてのアクティビティの基本クラスを作成しました。これには静的カウンターがあります。

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

これまでのところ、これで十分に機能しています。APIのバージョンに関係なく。もちろん、すべてのアクティビティーがこの基本クラスを拡張する必要があります-私の場合、それらを拡張します。

編集:アプリが完全に終了する前にカウンターがゼロに下がった1つのインスタンスに気づきました。これは、向きが変更され、1つのアクティビティのみが開いている場合です。向きが変わると、アクティビティが閉じて別のアクティビティが作成さonDestroyedれるため、最後のアクティビティに対して呼び出され、onCreate向きが変更された同じアクティビティが作成されたときに呼び出されます。この動作を考慮する必要があります。OrientationEventListenerが使用される可能性があります。


0

Androidはアクティビティスタックを実装していますここでそれを読むことをお勧めします。あなたがやりたいことは、呼び出しアクティビティを取得することだけのようです:getCallingActivity()。現在のアクティビティがアプリケーションの最初のアクティビティであり、アプリケーションがホーム画面から起動された場合、(私は)リターンするはずnullです。


9
アクティビティがstartActivityForResult()を介して開始されなかった場合、getCallingActivity()はnullを返すため、これは機能しません。
H9kDroid

0

ここで見逃したことの1つは、「ホームキー」のクリックです。アクティブにすると、アクティビティからこれを検出できません。そのため、「戻るキー」を押して必要なアクティビティに移動するか、プログラムでアクティビティスタックを制御する方がよいでしょう。必要なステップを実行するだけです。

さらに、「最近のアクティビティ」リストからのアクティビティの開始は、その場合に再利用されるため、アクティビティを開くための意図にいくつかの追加データを事前設定することで検出できることは確かではありません。

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