web-dev-qa-db-ja.com

HOMEを押した後にアプリケーションを再起動したときに、最後に起動したアクティビティに戻る方法は?

おなじみのシナリオ:Mainアクティビティがあり、Gameアクティビティを起動するボタンが押された。ユーザーがHOMEを押してからアプリケーションを再度起動すると、Gameアクティビティが表示されます。これは、応用。

ただし、代わりに、彼はMainアクティビティを再度取得します。 AndroidがMainActivityのインスタンスanotherを作成し、代わりにそのアプリケーションのスタックに追加している)と感じていますアプリを再起動した後で[戻る]を押すと、ゲームアクティビティが表示されるので、GameActivity.onResumeを呼び出す代わりに、Main.onCreateメソッドが毎回呼び出されます。

ぼくの AndroidManifest.xmlは、ほとんど 'ベアボーン'です。

<activity Android:name="MainActivity" Android:label="@string/app_name">
    <intent-filter>
        <action Android:name="Android.intent.action.MAIN" />
        <category Android:name="Android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity Android:name="GameActivity" Android:label="@string/app_name">
</activity>

ご覧のように、それほど凝ったものはありません。

そして、これは新しいアクティビティが開始される方法であり、非常に簡単です:

Intent intent = new Intent(this, GameActivity.class);
startActivity(intent);

理論的には、これはAndroid「箱から出してすぐ」のように機能するはずです。非常に類似した質問への答えが言うように: =Android(singleTask起動モードを使用) ですが、そうではありません。

私はアクティビティとタスクとスタックに関するドキュメントを読み、もう一度読み、関連するすべての回答をSO=で参照していますが、そのような単純な設定が期待どおりに機能しない理由を理解できません。

23
sole

ああ、私は答えを見つけたと思います。

IntelliJを使用してアプリを起動していたため、ユーザーがホーム画面ウィジェットをクリックして起動するのとは異なる方法でアプリケーションを起動しているようです。それは別のSO質問への回答で説明されています:

これは、アプリの起動に使用されるインテントが異なるためです。 Eclipseは、アクションもカテゴリもないインテントを使用してアプリを起動します。ランチャーは、Android.intent.action.MAINアクションとAndroid.intent.category.LAUNCHERカテゴリのインテントを使用してアプリを起動します。インストーラーはAndroid.intent.action.MAINアクションでアプリを起動し、カテゴリはありません。

参照: バックグラウンド状態を再開するのではなく、アプリは常にルートアクティビティから新しく開始します(既知のバグ)

そのため、私は電話でアプリケーションを手動で強制終了し、ホーム画面ウィジェットから再度再起動しました。次に、GameActivityを開き、HOMEキーを押しました。これで、再起動しても、GameActivityは表示されたままで、UIの状態は以前の状態のままです。

そして、以前にショートカットを押したときにアクティビティの新しいインスタンスが作成された理由は、アクティビティの開始に使用されている別のインテントが原因であったと思います。

18
sole
    @Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 
        // Activity was brought to front and not created, 
        // Thus finishing this will get us to the last viewed activity 
        finish(); 
        return; 
    } 

    // Regular activity creation code... 
} 
28
Sachin Gurnani

最も簡単な解決策は、onPause中に設定を書き出すか、状態を永続ファイルにシリアル化し、メインエントリポイントのアクティビティのonResume中にこのファイルを読み取ることです。このアクティビティは、アプリケーションの状態を再構築し、正しいアクティビティを再起動します。

アプリがmay終了時にOSによって強制終了されるため、これが表示されています。確かにわからないので、使用の真の永続性が必要な場合、つまり、何があっても最後のアクティビティに戻る場合は、状態を永続ストアに書き込む必要があります。

2
Andrew White

isTaskRoot を使用して、FLAG_ACTIVITY_BROUGHT_TO_FRONTフラグの代わりにアクティビティを終了する必要があるかどうかを確認することを強くお勧めします。

私は Sachinの答え が好きでしたが、時々それは私に偽陽性を与えて、私がすべきでないときに私は活動を終えるでしょう。このような誤検知を再現するために私が見つけた信頼できる方法は、次のとおりです。

  1. ホーム画面からアプリを起動します
  2. プレスホーム
  3. ホーム画面から再度アプリを起動しました
  4. 「戻る」を押してホーム画面に戻ります
  5. 「最近のアプリ」からアプリに戻りました

私は自分のタスクのアクティビティバックスタックを検査する方法を探し始め、ActivityManagerを使用して回答を見つけました。これはうまくいくように見えましたが、 この答えisTaskRoot の存在を指摘しました。これは、誤検知を与えず、特別な許可を必要とせず、ドキュメントに記載されているメソッドを使用しない、これを検出するシンプルでエレガントな方法であり、デバッグおよびタスク管理アプリ向けであり、このタイプの使用はサポートされていません。

2
DataGraham

私はあなたがどこから来たのか理解していますが、OSはどんな仮定もしたくないと思います。加えて、メモリが他の何かのために必要であるので、あなたのアプリが回収された問題があります。その原因では、MainActivityからやり直すことになります。

ゲームの複雑さに応じて、状態をSharedPreferencesに保存するか、アクティビティのonPause()メソッドでSqlLiteデータベースに保存できます。次に、onResume()を使用して、ユーザーを最後の状態に戻すことができます。これには、GameActivityの「再起動」が含まれる場合があります。

お役に立てれば!

編集:そして、私が言っているのは、アプリケーションに戻ったときに正しいアクティビティが表示されることをユーザーに表示/保証することは、開発者としての私たちの責任です。アプリケーションのメモリは常に再利用される可能性があり、Androidは、MAINおよびLAUNCHERインテントでラベル付けしたアクティビティを再開します。状態(アクティビティID)を保存することにより、それらをメインからそのアクティビティにリダイレクトできます...

1
bytebender

アプリケーションで次のアクティビティスタックを使用して問題を解決します。

LaunchActivity-> MainActivtiy-> SomeSubActivtiy

LaunchActivtiyは一部のパラメーターのみを検証し、MainActivtiyを起動します。 MainActivityは、

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

MainActivityのフラグの組み合わせにより、望ましい動作が得られます。

1
bivy