はじめに
画像シェア機能を扱う際にTaskやRecentについて色々と調査した結果を書き残しておきます。
taskとは
Taskはアプリで使用する一連のActivityの集まりで、内部的にはBackstackを用いてActivityを管理している。
task内のbackstackの挙動操作
ActivityのlaunchModeを指定することにより、Backstackの挙動を制御できます。設定方法は主に二つある:
- AndroidManifest.xmlでの設定
- Intentのフラグを使用した設定
AndroidManifest.xmlでの設定
AndroidManifest.xml内で以下のように設定する:
<activity android:launchMode="...">
</activity>
以下はlaunchModeのオプション:
- standard
- Backstackの最上部に新しいActivityインスタンスを追加する
- 異なるTask上に新しいActivityインスタンスを生成することができる
- singleTop
- 既にbackstackのトップにある場合はonNewIntent()を呼ぶだけ
- backstackの一番上でなければ新しいインスタンスを生成
- singleTask
- 新しいBackstackのルートとしてインスタンスを作成する
- 既存のインスタンスがある場合は、そのインスタンスにonNewIntent()を呼び出し、新しいルートにする
Flagでの設定
FLAG_ACTIVITY_NEW_TASK
-
launchMode
のsingleTask
と同じ
FLAG_ACTIVITY_SINGLE_TOP
-
launchMode
のsingleTop
と同じ
FLAG_ACTIVITY_CLEAR_TOP
-
launchMode
に該当するものはない - 既に存在するActivityのインスタンスがある場合、Backstack上でこのActivityの上にあるインスタンスをすべて削除し、onNewIntent()を呼び出す
-
FLAG_ACTIVITY_CLEAR_TOP
とFLAG_ACTIVITY_NEW_TASK
は一緒に使われることが多い- 新しいタスクでインスタンスを生成した時にBack Stackをclearできるから
task自体の操作
Recentから消したい場合
最近開いたアプリの一覧を見ることができると思いますが、それをRecentと呼びます。
Activityでfinish()
を呼び出すだけではTaskが削除されないので、Recentに残り続けてしまいます。これを回避したい場合はandroid:excludeFromRecents=”true”
をmanifestに設定するか、最後のactivityをfinishAndRemoveTask()
で終了させる必要があります。
taskのinstance管理
backstackの管理で使ったlaunchModeはActivityの生成を管理していて、taskを生成することに関しては何もできない。
そこでdocumentLaunchModeを使うことで、taskを生成したりすることができる。これを活用すると、一つのアプリで複数のTaskを作成し同時に二つのActivityの操作などが可能になります。
What is the difference between android:launchMode and android:documentLaunchMode attribute?
以下documentLaunchMode
で使えるオプションの引用(https://developer.android.com/guide/components/activities/recents?hl=ja#attr-doclaunch)
-
intoExisting
アクティビティがドキュメント用に既存のタスクを再利用します。これは、FLAG_ACTIVITY_MULTIPLE_TASK
フラグを設定せずにFLAG_ACTIVITY_NEW_DOCUMENT
フラグを設定した場合と同じです。上記のインテント フラグを使用したタスクの追加をご覧ください。 -
always
すでにドキュメントが開いている場合でも、アクティビティがドキュメント用に新しいタスクを作成します。この値の使用は、FLAG_ACTIVITY_NEW_DOCUMENT
フラグとFLAG_ACTIVITY_MULTIPLE_TASK
フラグの設定と同じです。 -
none
← これがデフォルト
アクティビティは、ドキュメント用に新しいタスクを作成しません。Recentでは、アクティビティがデフォルトとして扱われます。つまり、ユーザーが最後に実行したアクティビティから再開するアプリに対してタスクが 1 つ表示されます。 -
never
アクティビティは、ドキュメント用に新しいタスクを作成しません。この値を設定すると、FLAG_ACTIVITY_NEW_DOCUMENT
フラグとFLAG_ACTIVITY_MULTIPLE_TASK
フラグの動作がオーバーライドされます。いずれかがインテントに設定されている場合、Recentでは、ユーザーが最後に実行したアクティビティから再開するアプリに対してタスクが 1 つ表示されます。
画像シェアの際の細かい知見
他アプリから画像シェアなどで自アプリを開く場合のちょっとした知見です。
singleTask vs singleInstance
-
launchMode=singleTask
では、既存のTaskがある場合にその中のBackstackに追加されますが、singleInstanceでは既存のTaskのActivityをすべてクリアして唯一のActivityとなる。そのため、シェア画面などでは、シェア終了後に元のActivityに戻れるsingleTaskが理想的
Google files vs その他
- Filesはおそらく独自定義のせいでシェアした際のactivityがGoogle FilesのTask上に重なってしまう
- 以下を参考に、新しいintentをonCreateで呼ぶと通常通りFilesではなくこちらのアプリの上にactivityが作られる
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
if (!isTaskRoot()) { // Or check getIntent().getFlags() for SINGLE_INSTANCE
Intent newIntent = new Intent(getIntent());
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
finish();
}
}
さいごに
間違いなどありましたらコメントお願いします。