24
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Android Activity タスクとスタック

Last updated at Posted at 2020-03-16

アクティビティのタスクとスタックについてまとめます。間違っていたらご指摘のほどよろしくお願いいたします。

タスク

タスクは複数のアクティビティのまとまりのことです。公式ドキュメント1によると、

タスクは、ユーザーが新しいタスクを開始したとき、またはホームボタンを使用してホーム画面に移動したときに、「バックグラウンド」に移動できるまとまったユニットです。

です。端末のバックキーの反対側にある □ ボタンを押したら出てくる[最近]画面で、タスクの一覧を確認することができます。

アクティビティAがアクティビティBを起動すると、基本的には、それらのアクティビティはひとつのタスクに所属します。(後述しますが、別のタスクで起動することもできます。)
activities_2.png
注意したいのが、タスクは一つのアプリ内のアクティビティをまとめたものとは限らないということです。アプリが異なっても、同じタスクに所属する場合はあります。(むしろデフォルトの起動モードではそうなります)
activities_3.png

起動モード

アクティビティは起動モードという属性を設定できます。起動モードによって、どのタスクで起動するのかが変わります。

standard

1つのタスクに複数のインスタンスを生成でき、複数のタスクに跨って生成できます。デフォルトの起動モードです。
activities_launch_mode1.png

singleTop

1つのタスクに複数のインスタンスを生成できますが、タスクの一番上に既にある場合は、重ねてインスタンスを作成できません。複数のタスクに跨って生成できます。
activities_launch_mode2.png

singleTask

複数のタスクに跨って存在することはできません。端末内で同じアクティビティのインスタンスを持つタスクは1つだけになります。
activities_launch_mode3.png

singleInstane

複数のタスクに跨って存在することはできません。端末内で同じアクティビティのインスタンスを持つタスクは1つだけになり、さらに、そのタスク内には他のアクティビティは存在することができません。1タスク内に1つのアクティビティだけある状態になります。
activities_launch_mode4.png
singleTaskとsingleInstanceは、常に自身のタスクで(なければ新しく作成して)、アクティビティを起動したい場合にのみ使用します。

いろいろなアプリから呼び出されてもいい画面だけど、タスクはひとつにしたい、そういうときに使います。例えばブラウザアプリのアクティビティがsingleTaskになっています。いろいろなアプリからブラウザは呼び出されますが、常に自身のタスクで開きます。
activities_singletask_example.png

タスクの確認方法

起動中のタスクはコマンドで確認できます。

$ adb shell dumpsys activity activities

これでもいいですが、アクティビティの詳細情報も出力されて見にくいので、

$ adb shell dumpsys activity activities | sed -En -e '/Stack #/p' -e '/Running activities/,/Run #0/p'

とすると、タスク(とスタック)とタスクに属するアクティビティだけが出力され、見やすくなります。

タスクの状態は[最近]画面でもある程度わかるのですが、必ずしもタスク毎に分かれて表示されるわけではないので、起動したアクティビティが所属してるタスクを正確に把握したい場合は、コマンドで確認するといいと思います。

試しにstandardのアクティビティから別のstandardのアクティビティを起動した時のタスク状態をみてましょう。
(API level 28 のエミュレータで試しました)

  Stack #106: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{b418524 #99 A=jp.favolabo.activitystart U=0 StackId=106 sz=2}
        Run #1: ActivityRecord{a2296cf u0 jp.favolabo.activitystart/.StandardTwoActivity t99}
        Run #0: ActivityRecord{fec21ab u0 jp.favolabo.activitystart/.StandardOneActivity t99}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}

StandardOneActivityStandardTwoActivityを起動したんですね。NexusLauncherActivityというのはホーム画面のアクティビティになります。

IntentにフラグをつけてActivityを起動

FLAG_ACTIVITY_NEW_TASK というフラグがあります。実は、アクティビティの起動モードをsingleTaskにすると、このフラグが設定されて起動されています。コードで書くと以下のようになります。

Activity.kt
val intent = Intent(this, StandardActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)

なので動的にstandardのアクティビティをsingleTaskのように起動したい場合があれば、上記のように設定すればよいかと思います。

ちなみにですが、さきほどのタスクを確認するコマンドで、アクティビティの詳細情報まで出力して

  • standardのアクティビティにFLAG_ACTIVITY_NEW_TASKをつけて起動した場合
  • singleTaskのアクティビティを普通に起動した場合

を見比べてみると、

```:standardのアクティビティにFLAG_ACTIVITY_NEW_TASKをつけて起動した場合
Intent { flg=0x10000000 cmp=jp.favolabo.activitystart/.StandardActivity }


```:singleTaskのアクティビティを普通に起動した場合
Intent { flg=0x10000000 cmp=jp.favolabo.activitystart/.SingleTaskActivity }

とIntentの情報があり、flgが同じ(=FLAG_ACTIVITY_NEW_TASK)であることがわかります。

taskAffinity

singleTaskのアクティビティを起動するときに、どのタスクで起動すべきかを決めるための属性として、taskAffinity(親和性)というものがあります。

ためしに、同じアプリでsingleTaskのアクティビティをstandardのアクティビティから起動してみます。すると、同じタスク上で起動します。

これはなぜかというと、taskAffinityが同じアクティビティは、同じタスク内に起動しようとするからです。
taskAffinityはデフォルトではパッケージ名になります。たとえば com.hoge.fuga.app というパッケージ名だと、そのアプリ内のアクティビティのtaskAffinityも com.hoge.fuga.app になります。
activities_taskaffinity.png

必ず別タスクでsingleTaskのアクティビティを起動したい場合は、taskAffinityを明示的に指定します。

AndroidManifest.xml
<activity android:name=".SingleTaskActivity"
    android:launchMode="singleTask"
    android:taskAffinity="app.hoge.fuga2"/>

どのタスクでアクティビティが起動するか、こちら2 の解説記事でわかりやすく、起動モードごとにアニメーション付きで説明されていますので、是非見てみてください。

スタック

アクティビティを起動すると、後入れ先出しのいれもの(スタック)に積まれます。バックボタンを押すと、現在表示中のアクティビティから順に取り出されて、ホーム画面が表示されるまで、一つ前のアクティビティに戻っていきます。

例えばsingleTaskアクティビティであるブラウザを呼び出した場合は、以下のようなスタックになります。

  Stack #120: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{45197fa #113 A=com.android.chrome U=0 StackId=120 sz=1}
        Run #0: ActivityRecord{976c635 u0 com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity t113}
  Stack #119: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{86811ab #112 A=jp.favolabo.activitystart U=0 StackId=119 sz=1}
        Run #0: ActivityRecord{847e274 u0 jp.favolabo.activitystart/.StandardActivity t112}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}

ブラウザでバックボタンを押していくと、
ブラウザ(ChromeTabbedActivity) → StandardActivity → ホーム画面(NexusLauncherActivity
の順で取り出されていきます。
activities_pop1.png

ここで、試しにブラウザが表示されたら、ホームボタンを押して、呼び出し元のアクティビティ(StandardActivity)をアイコンからタップして起動してみましょう。するとスタックは以下のように変わりました。

  Stack #119: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{86811ab #112 A=jp.favolabo.activitystart U=0 StackId=119 sz=1}
        Run #0: ActivityRecord{847e274 u0 jp.favolabo.activitystart/.StandardActivity t112}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}
  Stack #120: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{45197fa #113 A=com.android.chrome U=0 StackId=120 sz=1}
        Run #0: ActivityRecord{976c635 u0 com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity t113}

スタックの一番上がStandardActivityになっていて、次にホーム画面(NexusLauncherActivity)になっていますね。なので、当たり前ですが、バックボタンを押すと、ホーム画面に戻ります。
activities_pop2.png

参考

親和性と新しいタスク
アクティビティのリファレンス

  1. タスクとバックスタックについて

  2. 起動モードのチートシート

24
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?