📝

singleTaskなのにonNewIntentが呼ばれない? App Links実装でハマった話

に公開

1. はじめに

Androidで App Links を実装する際、
Activity に launchMode="singleTask" を指定していました。

androidmanifest.xml
<activity
    android:name=".HomeActivity"
    android:launchMode="singleTask" />

singleTask を利用しているため、

  • Activity が再利用される
  • onNewIntent() が呼ばれる

という前提で実装を進めていました。

しかし、実際には想定と異なる挙動が発生しました。

本記事では、App Links 実装時に遭遇した singleTaskonNewIntent() に関する挙動について整理します。

2. 想定していた挙動

App Links でアプリが起動された場合、
既存の Activity が存在していれば onNewIntent() が呼ばれる想定でした。

HomeActivity.kt
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)

    handleDeepLink(intent)
}

つまり、singleTask = onNewIntent が呼ばれる という認識でした。

3. 実際に発生した問題

実際には、以下のようなケースが発生しました。

  • onNewIntent() が呼ばれる場合がある
  • onCreate() が呼ばれる場合がある
  • 期待していた処理が実行されない場合がある

特に問題になったのは、
履歴から Activity が復元されたケースです。

この場合、App Links の再実行を想定していた処理が
意図せず再度動作してしまいました。

4. 原因

原因は singleTask の挙動を誤解していたことでした。

singleTask は、

  • Activity の生成方法
  • Task の扱い

に影響を与えますが、必ず onNewIntent() が呼ばれる ことを保証するものではありません。

Androidでは、

  • Task の状態
  • バックグラウンド復帰
  • 履歴からの復元
  • Intent の再配送

などによって挙動が変化します。

つまり、launchModeは挙動を完全に保証するものではない という点を理解する必要があります。

また、Androidではメモリ不足などにより、OSがバックグラウンドのProcessを終了させる場合があります。

このような Process Death が発生した場合、Activityは既存インスタンスとして再利用されず、復元時に onCreate() から再実行されます。

そのため、singleTask を指定していても、
常に onNewIntent() が呼ばれるとは限りません。

5. 実際に行った対応

今回のケースでは、
履歴から復元された Intent を判定し、
不要な再処理を行わないように対応しました。

HomeActivity.kt
if ((intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
    return
}

また、

  • onCreate()
  • onNewIntent()

の両方で Intent を考慮するように実装を見直しました。

6. なぜハマりやすいのか

この問題が厄介なのは、
singleTask の説明だけを見ると、「既存 Activity が再利用される」 という印象を受けやすいためです。

しかし実際には、

どの lifecycle が呼ばれるか

まで単純には決まりません。

そのため、

singleTask にしたから安心

という実装は危険です。

7. まとめ

今回のポイントは以下です。

  • singleTask は onNewIntent() を保証しない
  • App Links では履歴復元を考慮する必要がある
  • launchMode だけに依存した実装は危険
  • Intent の状態を考慮した制御が重要

8. おわりに

Android の launchMode は便利ですが、
内部挙動を正しく理解していないと、
想定外の lifecycle が発生することがあります。

特に App Links のように
「再起動」や「復帰」が絡む機能では、
実際の挙動を確認しながら設計することが重要だと感じました。

ファースト・スクラッチTech Blog

Discussion