web-dev-qa-db-ja.com

Androidアプリインストーラーおよびホーム画面からアプリケーションを起動するときのアクティビティスタックの順序の問題

テスト目的でのみ、アプリAPKをダウンロードしてURL経由でインストールすることを許可しています。電話にダウンロードしたら、Androidアプリインストーラーで起動できます。これにより、ユーザーはデバイスにインストールして実行することができます。

上記の方法でアプリをダウンロードして実行したかどうかを検討します。私のアプリのメイン/ランチャーアクティビティはログインページ(_Activity A_)です。ユーザーが認証されると、ユーザーはアプリケーションのメインエリアに移動します。 _Activity B_。したがって、このタスクの現在のアクティビティスタックは_A > B_です。

次に、電話のホームボタンを押すと、Androidホーム画面に移動します。メニューのアイコンからアプリを再起動すると、_Activity A_に移動します、_Activity B_の代わりに。アクティビティスタックは_A > B > A_になりました。または、アクティビティスタック_A > B_、およびAを持つ2つの個別のタスクがあります。アプリを再起動すると、_Activity B_に戻ります。この状態で[戻る]を押すと、_Activity B_に戻ります。

この望ましくない動作は、最初にインストーラーを介してアプリを開いた場合にのみ発生し、ホーム画面/メニューを介してアプリを開いた場合には発生しません。

それぞれの仕組みがどのように活動を始めているのか調べました。アプリインストーラーを使用すると、次のログが表示されます。

_INFO/ActivityManager(XXXX): Starting activity: Intent { dat=file:///mnt/sdcard/download/[my app].apk cmp=com.Android.packageinstaller/.InstallAppProgress (has extras) }
INFO/ActivityManager(XXXX): Starting activity: Intent { act=Android.intent.action.MAIN flg=0x10000000 cmp=[my package]/[Activity A] }
_

ランチャー/ホーム画面経由:

_INFO/ActivityManager(XXXX): Starting activity: Intent { act=Android.intent.action.MAIN cat=[Android.intent.category.LAUNCHER] flg=0x10200000 cmp=[my package]/[Activity A] }
_

インストーラーで開始すると、フラグ_0x10000000_を使用していることがわかりますが、ランチャーで開始すると、_0x10200000_を使用していることがわかります。インテントカテゴリも使用しています。

docs から、フラグは次のようになります。

_public static final int FLAG_ACTIVITY_NEW_TASK
Constant Value: 268435456 (0x10000000)

public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
Constant Value: 2097152 (0x00200000)
_

フラグ_FLAG_ACTIVITY_RESET_TASK_IF_NEEDED_(アプリがランチャーから起動されたときに使用されます)は、通常、新しいタスクが既に存在する場合に作成されないようにし、最後に使用されたアクティビティを復元します。これは望ましい動作です。なぜこの状況で機能しないのですか?アプリのインストーラーやランチャーから開始したかどうかに関係なく、アプリケーションが常に最後のアクティビティに戻るようにするためにできることはありますか?

singleTaskを使用すると、アプリを実行するたびにメインのアクティビティ(_Activity A_)に戻ります(これも望ましくありません)。

ここで私が見つけた質問は、誰かが同様の問題を抱えていることを発見しました(受け入れられた回答はありません): 別のアプリケーションから起動すると、アプリはスタックを記憶する能力を失います

編集:ランチャーアクティビティのonCreate()にあるフラグ_FLAG_ACTIVITY_BROUGHT_TO_FRONT_を確認すると(それが設定されている場合は終了します)、主な症状は修正されているようですが、根本的な問題がまだ残っています。より完全な修正はありますか?

EDIT2:Android Marketからアプリをダウンロード/実行すると同じ結果が発生するため、上記の詳細の一部は関係がない場合があります。

51
antonyt

Antonytが提供した答えを追加しました:

@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...
}
30

根本的な問題は、使用されるIntentsがランチャーとインストーラーで異なることです。異なるIntentフラグを取得している限り、起動動作は異なります。起動モードを変更すると、一貫した結果が得られる可能性がありますが、基本的に、これらの異なるインテントは異なる結果を生成します。

あなたの修正(または this など)がおそらく最善の策です。

12
Femi

問題の原因は、アプリインストーラーがランチャーと同様にLAUNCHERカテゴリーを使用していないことにあります。

このバグは他の場所で文書化されています:

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

0
Nathan Fig