Developer's Blog

【 Android N 】 マルチウィンドウ機能の使用方法をまとめました

こんにちは。アプリケーション共同開発部の岸本です。

Android N から、複数のアプリを同時に表示するためのマルチウィンドウという機能が追加されます。
このマルチウィンドウ機能をサポートするために使用方法を調査しました。
アプリ開発やテストの際に参考になれば幸いです。

※ Preview 版での確認となりますので、今後動作が変わる可能性があります。

(2016/07/21 16:00) Preview 5 での調査結果を追記

  • split mode でのサイズ変更で Activity が再生成されることがある
  • freeform mode での画面回転時の再生成は Preview 4 から変化なし

準備

まず、マルチウィンドウ機能は以下の3つに分類されます。

  • split mode
  • freeform mode
  • picture in picture

picture in picture は、Android TV の機能ですので、本記事では split mode, freeform mode について記載します。
freeform mode はメーカーが有効にした端末で使用できる機能ですが、以下のコマンドで有効にし、確認しました。

$ adb shell settings put global enable_freeform_support 1

上記コマンドを実行した後に端末を再起動すると、Overview Screen にて、freeform mode を起動するボタンが表示されます。

freeform mode の開始ボタン

無効にする際は以下のコマンドを実行してください。

$ adb shell settings delete global enable_freeform_support

調査内容

マルチウィンドウ機能(split mode, freeform mode)をどのように使用するのか?また、使用した時の動作、及びアプリのライフサイクルについて調査します。

確認端末には、Nexus 5X(Android N Preview 4, Preview 5) を使用し、
動作確認用アプリには Google 社のサンプルアプリを一部修正して使用します。

split mode の使用方法

※ 上領域、下領域という記載がありますが、端末を縦にした状態で調査しています。

マルチウィンドウを開始する

以下の手順のいずれかで、マルチウィンドウ機能を開始できます。

Overview Screen でアプリを長押しして、ドラッグ & ドロップ

上領域にドロップすると、アプリはフォーカスされた状態で起動され、下領域には Overview Screen が表示されます。

呼び出されるライフサイクルのメソッドは通常のアプリ起動と同様です。

onCreate
onStart
onPostCreate
onResume
onWindowFocusChanged: true

アプリ起動中に Overview キーを長押し

起動していたアプリが上領域に表示され、下領域には Overview Screen が表示されるとともに、下領域がフォーカスされた状態となります。

onWindowFocusChanged: false
onMultiWindowModeChanged: true
onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onPause

フォーカス状態を切り替える

アプリの画面をタップすると、フォーカス状態が切り替わります。
タップされたアプリでは、onResume が実行され、フォーカスされた状態に、
もう一方のアプリでは、onPuase が実行され、フォーカスが外れた状態となります。

表示領域のサイズを変更する

split mode でのサイズ変更

分割線をドラッグすると、領域のサイズを変更することができます。サイズを確定すると、onConfigurationChanged が呼び出されます。

onConfigurationChanged: {1.0 ?mcc?mnc [ja_JP,en_US,en_XA] ldltr sw336dp w411dp h418dp 420dpi smll port finger -keyb/v/h -nav/h s.21}

Preview 5 では、onConfigurationChanged の代わりに Activity が再生成される場合もあります。(2016/07/21 16:00追記)

onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume

マルチウィンドウを中断する

以下のいずれかの手順を実施すると、マルチウィンドウ機能が中断されます。

マルチウィンドウ中にホームキーをタップ

中断時にアプリが上領域にあるとライフサイクルは

onWindowFocusChanged: false
onPause

となり、通常のアプリの中断と異なり、onStop は呼び出されません。

下領域にアプリがある状態で中断すると、

onWindowFocusChanged: false
onPause
onSaveInstanceState
onStop

通常のアプリの中断と同じライフサイクルとなります。

下領域のアプリをバックキーで終了

上領域にアプリがある場合は、下領域のアプリをフォーカスした時点で、
onPause まで呼ばれているので、中断されてもその他のライフサイクルのメソッドは呼び出されません。

下領域にアプリがある場合は、通常のアプリ終了と同じで

onWindowFocusChanged: false
onPause
onStop
onDestroy

となります。

マルチウィンドウを復帰する

マルチウィンドウ中断中に以下のいずれかの手順でマルチウィンドウを復帰できます。

マルチウィンドウ中断中に Overview キーをタップ

split mode 中断中

この状態で、Overview キーをタップすると、マルチウィンドウが復帰します。
上領域は中断前のアプリで復帰しますが、下領域は Overview Screen がフォーカスされた状態で復帰します。

復帰時は、下領域に Overview Screen がフォーカスされた状態で表示されるので、ライフサイクルのメソッドは何も呼び出されません。

マルチウィンドウ中断中にホームアプリからアプリ起動

上領域に表示されていたアプリを起動すると、
Overview キータップと同じく、下領域がフォーカスされた状態で復帰しますが、
ライフサイクルは一度 onResume が呼び出されます。

onResume
onPause

下領域に表示されていたアプリを起動すると、下領域にアプリが表示、フォーカスされた状態で復帰します。

onStart
onResume
onWindowFocusChanged: true

中断前に表示していなかったアプリを起動すると、下領域にアプリが表示、フォーカスされた状態で復帰します。
ライフサイクルは通常のアプリ起動と同じとなります。

onCreate
onStart
onPostCreate
onResume
onWindowFocusChanged: true

ただし、マルチウィンドウでの起動が不可能なアプリを選択した場合は、
マルチウィンドウが解除され、通常通りアプリが起動されます。

マルチウィンドウを終了する

以下のいずれかを行うと、マルチウィンドウが終了します。

  • マルチウィンドウでの起動が不可能な画面へ遷移
  • 上領域のアプリをバックキーで終了
  • マルチウィンドウの境界線をドラッグし、画面上部、もしくは下部へ移動させる

マルチウィンドウ中のアプリ内の画面遷移

マルチウィンドウで起動しているアプリで画面遷移すると以下の動作となります。

  • マルチウィンドウでの表示が可能な画面への遷移であれば、同じ領域で画面遷移する
  • マルチウィンドウでの表示が不可能な画面への遷移であれば、マルチウィンドウが解除される
  • Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK をセットして起動すると、表示中の領域とは別の領域で表示される

マルチウィンドウ中の画面回転

マルチウィンドウ中に画面回転すると、フォーカス状態が維持されたままとなります。

フォーカスされている状態の場合は、

onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onWindowFocusChanged: true

となり、通常状態での画面回転と同じとなります。

フォーカスされていない状態の場合は、

onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onPause

となります。

android:configChanges =”screenSize|orientation” を指定し、画面回転によって再生成されないようにした画面では、
フォーカスされている / いないに関わらず、onConfigurationChanged のみが呼び出されます。

freeform mode の使用方法

マルチウィンドウを開始する

Overview Screen の各アプリに表示されているボタンをタップすると、フォーカスされた状態でアプリが起動します。

onCreate
onStart
onPostCreate
onResume
onWindowFocusChanged: true

また、前回 freeform mode で使用していたアプリを Overview Screen でタップすると、
freeform mode が開始されます。
ライフサイクルは上記と同じでした。

フォーカス状態を切り替える

split mode と同じとなります。

表示領域のサイズを変更する

画面の上下左右の端をドラッグするとサイズを変更できます。

split mode と異なり、サイズ変更中は onConfigurationChanged がサイズ確定まで呼び出し続けられます。

onConfigurationChanged: {1.0 ?mcc?mnc [ja_JP,en_US,en_XA] ldltr sw336dp w220dp h342dp 420dpi smll port finger -keyb/v/h -nav/h s.13}
onConfigurationChanged: {1.0 ?mcc?mnc [ja_JP,en_US,en_XA] ldltr sw336dp w220dp h343dp 420dpi smll port finger -keyb/v/h -nav/h s.13}
onConfigurationChanged: {1.0 ?mcc?mnc [ja_JP,en_US,en_XA] ldltr sw336dp w220dp h344dp 420dpi smll port finger -keyb/v/h -nav/h s.13}

表示領域の位置を変更する

アプリの Toolbar の上に freeform mode 用のバーが表示されており、
ここをドラッグすると、表示位置を移動することができます。

移動中は、サイズ変更と同じで onConfigurationChanged が呼び出し続けられます。

マルチウィンドウを中断する

ホームキー、Overview キーをタップ

フォーカスされた状態で中断すると、

onWindowFocusChanged: false
onPause
onSaveInstanceState
onStop

フォーカスされていない状態で中断すると、

onSaveInstanceState
onStop

となります。

アプリ上部に表示されているバーにあるボタンをタップ

マルチウィンドウ (freeform mode) 中は、アプリの上部にバーが表示され、ボタンが2つ表示されます。

freeform mode 実行中

マルチウィンドウで複数のアプリが表示されている状態で、
左側のボタンをタップすると、アプリが全画面で表示され、マルチウィンドウが中断されます。

onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onMultiWindowModeChanged: false
onWindowFocusChanged: true

の様に画面が破棄されて再生成されています。

マルチウィンドウを復帰する

Overview Screen からアプリ選択

freeform mode 中断中

この画面でアプリを選択すると、選択したアプリがフォーカスされた状態で、マルチウィンドウが復帰します。
アプリ領域のサイズ、位置は中断前と同じ状態で復帰します。

ホームアプリからアプリを起動

中断前に表示していたアプリをホームアプリから起動すると、マルチウィンドウが復帰します。
表示していないアプリを起動すると、マルチウィンドウでの起動が可能 / 不可能に関わらず、全画面でアプリが起動されます。

その後、Overview キーをタップすると、

freeform mode 中断中2

となり、設定アプリをタップすると、マルチウィンドウが復帰するので、
マルチウィンドウが終了するわけではないようです。

マルチウィンドウを終了する

×ボタンやバックキーなどで、マルチウィンドウに表示されているアプリを全て終了すると、 マルチウィンドウも終了します。

マルチウィンドウ中のアプリ内の画面遷移

マルチウィンドウで起動が可能な画面へ遷移する場合は、マルチウィンドウで表示されますが、
起動する Activity の launchMode や、起動時のフラグによって動作が異なります。

launchMode 動作
指定なし or standard 同ウィンドウにて画面表示
singleTop 同ウィンドウにて画面表示
singleInstance 別ウィンドウにて画面表示
singleTask 別ウィンドウにて画面表示

タスク毎にウィンドウが表示される動作となっており、
Intent.FLAG_ACTIVITY_NEW_TASK を付加して起動しても、別ウィンドウで画面が表示されます。

マルチウィンドウでの起動が不可能な画面への遷移の場合は、マルチウィンドウが解除され、全画面で表示されます。

マルチウィンドウ中の画面回転

フォーカスされている状態の場合は、

onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onWindowFocusChanged: true

フォーカスされていない状態では、

onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onPause
onSaveInstanceState
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onPostCreate
onResume
onPause

となりました。

この動作は split mode と同じになると想定していたのですが、
Preview 4 では、split mode と freeform mode で異なっていました。
freeform mode では 破棄 -> 生成 が 2回呼び出されています。
(Preview 5 でも同じ動作となりました。(2016/07/21 16:00追記))

念のため、エミュレータでも確認しましたが、同現象となりました。
(この現象については引き続き調査し、何か分かりましたら本記事を更新させて頂きます。)

android:configChanges =”screenSize|orientation” を指定し、画面回転によって再生成されないようにした画面では、
split mode と同じく onConfigurationChanged のみが呼び出されます。

参考

Multi-Window Support
Designing for Multi-Window
Multi-Window mode – Google I/O 2016

フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

フェンリルの開発者アカウントでは、フェンリルプロダクトの最新開発情報などをつぶやいています。よろしければフォローしてください!

フェンリルの Facebook ページでは、最新トピックをお知らせしています。よろしければいいね!してください!

Copyright © 2019 Fenrir Inc. All rights reserved.