今すぐできる! Android 7.0の新機能「マルチウィンドウ」をアプリ開発で活用する方法 (2/2)|翔泳社の本

今すぐできる! Android 7.0の新機能「マルチウィンドウ」をアプリ開発で活用する方法

2016/11/28 07:00

講義 マルチウィンドウについて

マルチウィンドウとは

 Android 7.0(Nougat)ではマルチタスク機能を強化するためにマルチウィンドウが追加されました。もともとAndroid OSは、画面上に表示・動作できるActivityは1つまででしたが、マルチウィンドウを使うと複数のActivityを1画面で同時に表示できます。わかりやすい例を挙げると、ドキュメントアプリで資料を見ながらメールアプリを使う、Twitterアプリを使いながらブラウザアプリでWebページの閲覧、といった操作がマルチウィンドウでは可能になります。

 とはいえ、Androidユーザーだった方にはそれほど革新的な機能ではないかもしれません。なぜならSAMSUNG、Huawei、LG等の一部のAndroidデバイスメーカーでは、数年前から独自機能としてアプリのマルチウィンドウ機能がサポートされていました。あるいはシステムオーバーレイ上にLayoutやViewを追加してActivityを使わずに複数の画面を表示するテクニックも存在していたためです。いずれにせよ、Android 7.0(Nougat)で正式にマルチウィンドウがサポートされたのは大きな変化といえます。

マルチウィンドウの操作方法

 マルチウィンドウには専用の切り替え操作が必要です。切り替え方法には表1の方法があります。

表1 マルチウィンドウの切り替え方法
表1 マルチウィンドウの切り替え方法
図4、図5
左:図4 オーバービューボタンを長押しでマルチウィンドウへ移行
右:図5 オーバービュー画面からマルチウィンドウへ移行

 なお、マルチウィンドウモードを解除する場合はオーバービューボタンを再度長押しするか、分割線を画面端までドラッグしてどちらか片方のアプリを全画面にすることで解除できます。

マルチウィンドウの種類

 マルチウィンドウはデバイスの種類に応じて画面分割モード、ピクチャーインピクチャー(以下PinP)モード、フリーフォームモードの3種類が用意されています。「デバイスの種類に応じて」というところがミソであり、ややこしいところなのですが、Androidはスマートフォンだけに限らず、タブレット、TV(テレビ)、Wear(ウェアラブル)、Auto(カーナビ)とさまざまなプラットフォームが存在するため、プラットフォームに応じて最適なマルチウィンドウが選ばれるようになっています。各マルチウィンドウの特徴は以下のようになっています。

画面分割モード

 画面分割モードはスマートフォン・タブレットで利用できるマルチウィンドウです。ディスプレイの向きに応じてポートレートでは上下、ランドスケープでは左右に2つ並べて表示できます(図6)。分割領域にある分割線をドラッグすることで片方のアプリを拡大、もう片方を縮小といったようにサイズ比率を変更することもできます。後述するPinPモード、フリーフォームモードは特殊なので、Androidのマルチウィンドウ機能といえばこの画面分割モードがスタンダードなモードといえます。

図6 画面分割モードのイメージ
図6 画面分割モードのイメージ

ピクチャーインピクチャー(PinP)モード

 PinPモードはAndroid TVで利用できるマルチウィンドウです。テレビ番組のワイプのように、メインとなるアプリを表示しつつ、4隅のいずれかのコーナーに別のアプリを表示することができます(図7)。ただしPinPのウィンドウは240x135dpとサイズが小さく限られていることもあり、表示できるUIやレイアウトは限られたものになります。実際の使用用途として動画再生アプリのPinP表示で使うのがほとんどかもしれません。またPinPモードに限ってはユーザー操作でマルチウィンドウに切り替えるのではなくenterPictureInPictureModeメソッドを使用してプログラムで切り替える必要があります。

図7 PinPモードのイメージ
図7 PinPモードのイメージ

フリーフォームモード

 フリーフォームモードはスマートフォン・タブレットで利用できるマルチウィンドウです。アプリをウィンドウ化させてPCのようにディスプレイ上に自由に配置できるようになります(図8)。またこのモードに限ってアプリを2つよりも多く配置できます。なお、執筆している2016年9月現在、フリーフォームモードは販売するAndroidデバイスメーカーが機能を有効にした場合に利用できるモードとされています。フリーフォームモードはディスプレイサイズが大きくないとかえって使い勝手が良くないので、オプション的な位置付けとなっているようです。

 ちなみにN Preview のシステムイメージではデフォルトは無効となっていますが、特定の操作を行うことでフリーフォームモードを有効にすることができます(最後の補講で紹介)。

図8 フリーフォームモードのイメージ
図8 フリーフォームモードのイメージ

マルチウィンドウのライフサイクル

 Android開発者でマルチウィンドウ機能を目にした時に、まずライフサイクルを気にする人も多いのではないでしょうか。筆者もその1人でした。Androidでは表示中のActivityだけがアクティブ状態になるのが今までの常識で、開発者はこのルールにしたがってアプリの初期化、再開、中断、終了等の処理を実装していました。そのためマルチウィンドウで画面に2つもアプリが表示されるとActivityのライフサイクルは一体どう管理すれば良いのか疑問に思ったのです。

 でも大丈夫です。マルチウィンドウであってもActivityのライフサイクルに変更はありません。たとえば画面分割モードの場合、現在操作しているActivityだけがアクティブ状態となり、もう片方のActivityは表示されていても、onPauseメソッド(一時停止状態)となります。実習で作成したサンプルはライフサイクルの流れがわかるようにログをリスト表示できるようにしているので、実際に動かしてみるとActivityのライフサイクルがどうなっているのか確認しやすいでしょう。

 ただし、ライフサイクル自体に変更はないもののライフサイクルの流れには変化があるという点に注意してください。通常Activityを切り替えた場合、Activityの表示・非表示フェーズが存在するためonStart(Activity表示)、onStopメソッド(Activity非表示)が呼ばれます。しかしマルチウィンドウで画面上に表示しているActivityを切り替えた場合は、Activityの表示状態が変化するわけではないのでonStart、onStopメソッドが呼ばれません。これが意味することは、もし初期化処理や再開処理をonStartメソッド、停止処理や終了処理をonStopメソッドで実装している場合は、マルチウィンドウ時のみ動作しないということです。たとえばGPSセンサーを利用するアプリでonStopメソッドにGPSの停止処理を実装していたとしたら、マルチウィンドウでアプリを切り替えてもGPSセンサーは動きっぱなしになります。もちろんそれが正しい動作であるなら良いのですが、非アクティブ時にGPSセンサーを動作させる必要がないのであれば、バッテリー消費が激しい間違った実装になってしまいます。マルチウィンドウでも正しくアプリを動作させたい場合は、どのライフサイクルでどの処理が必要か検討した上で実装するように心がけてください。

マルチウィンドウ向けアプリの構築

 マルチウィンドウの制御に関して細かく設定する場合は、Android 7.0(Nougat)であるAPIレベル24をターゲットSDKに指定する必要があります。APIレベル23以下をターゲットにした場合は、android:screenOrientation属性を指定していなければ強制的にマルチウィンドウに、指定していればマルチウィンドウにならず全画面で表示されます(表2)。

表2 ターゲットSDKに指定するAPIレベルとマルチウィンドウの関係
表2 ターゲットSDKに指定するAPIレベルとマルチウィンドウの関係

マルチウィンドウの種類に関する属性

 APIレベル24ではマルチウィンドウの有効/無効、および、どのモードを利用するかの設定を属性で指定できます。表3はそれらの属性を説明したものです。

表3 マルチウィンドウサポートに関する属性
表3 マルチウィンドウサポートに関する属性

 表3の属性をtrueに設定した場合はマルチウィンドウモードのサポートを有効にします。falseを指定した場合は無効にします。この属性はノード、ノードどちらにも適用できます。アプリ全体に適用したい場合は前者、Activityごとに設定したい場合は後者に記述するようにしましょう。なお、APIレベル24をターゲットにしている場合、この属性を省略してもデフォルトでtrueの状態が適用されます。

表4 PinPモードに関する属性
表4 PinPモードに関する属性

 表4の属性をtrueに設定した場合、PinPモードのサポートが有効になります。前述したようにPinPモードはAndroidTVプラットフォームで有効なモードなので普段スマートフォン・タブレットを対象にアプリを開発する場合は利用することのない属性です。

マルチウィンドウのレイアウトに関する属性

 同じくAPIレベル24ではマルチウィンドウ時のActivityサイズを指定できる属性が追加されています。表5はそれら属性を説明したものです。

表5 マルチウィンドウのサイズに関する属性
表5 マルチウィンドウのサイズに関する属性

 フリーフォームモード時のデフォルトのWidth(幅)、Height(高さ)をdpで指定します。フリーフォームモードにするとアプリがウィンドウ化する都合上、画面サイズの幅が約90%、高さが70%ほどに縮みます(図9)。あらかじめフリーフォームモード時のサイズを指定したい場合は、この属性を指定することで最適なサイズでフリーフォームモードへ移行できます。なお、2016年9月現在、N Previewではこの属性は機能していません。

図9 右がフリーフォームモード時のActivityのサイズ
図9 右がフリーフォームモード時のActivityのサイズ
表6 マルチウィンドウの表示位置に関する属性
表6 マルチウィンドウの表示位置に関する属性

 表6の属性はフリーフォームモード時にアプリが配置される位置(gravity)を指定します。フリーフォームモードの場合、アプリを画面上の好きな位置に配置できるため、gravity属性を使用してデフォルトの表示位置を指定できるようになっています。この属性も2016年9月現在、N Previewでは機能していません。

表7 マルチウィンドウの最小サイズに関する属性
表7 マルチウィンドウの最小サイズに関する属性

 表7の属性は画面分割モード・フリーフォームモード時の最小幅(Width)、高さ(Height)をdpで指定します。これ以上サイズを縮めるとアプリのUI/UXに支障をきたすといった場合は、この属性で最小サイズを指定することで回避できます。2016年9月現在、筆者が試しているN Previewではフリーフォームモードのみ機能しています。

図10 左はデフォルトの最小サイズ、右はminWidth、minHeightでさらに小さく指定した状態
図10 左はデフォルトの最小サイズ、右はminWidth、minHeightでさらに小さく指定した状態

 なお、表5、6、7のサイズに関する属性をActivityにセットしたい場合はAndroid Manifest.xml上でリスト6のように設定します。

リスト6 Activityにマルチウィンドウのサイズ属性をセット
<activity
  android:name=".MainActivity"
  android:label="@string/app_name">
  <layout
    android:defaultWidth="320dp"
    android:defaultHeight="320dp"
    android:gravity="end"
    android:minHeight="160dp"
    android:minWidth="160dp" />
</activity>

マルチウィンドウを実装する際に利用する代表的なメソッド

 表8のisInMultiWindowModeメソッドを使うと現在Activityがマルチウィンドウかどうかを調べることができます。戻り値がtrueの場合はマルチウィンドウ、falseの場合は全画面(通常の起動)と判断することができます。IsInPictureInPictureModeメソッドはPinPモードかどうかを調べるメソッドで、こちらもtrueであればPinPモード、falseであればPinPモードになっていないと判定することができます。現在の画面モードに応じて処理を切り分けたい場合はこのメソッドを使用して判定しましょう。

表8 現在の画面モードを確認するメソッド
表8 現在の画面モードを確認するメソッド

 表9のonMultiWindowModeChangedメソッドは全画面とマルチウィンドウが切り替えるたびに呼ばれます。引数がboolean型になっていてisInMultiWindowModeの値がtrueならマルチウィンドウ、falseなら全画面モードと判定できるようになっています。もし画面モードが切り替わった直後に、画面モードに応じて特定の処理を実装したい場合はこのメソッドをオーバーライドすると実現できます。onPictureInPictureModeChangedメソッドも同様の使い方ができ、こちらはPinPモードの切り替えを検出することができます。

表9 画面モードの切り替えを検出するメソッド
表9 画面モードの切り替えを検出するメソッド

新しいウィンドウでActivityを起動する方法

 画面分割モード時に、IntentフラグにIntent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASKを指定してstartActivityメソッドを呼び出すと隣の分割領域に新たにActivityを起動することができます(実習のリスト3)。ただしこの操作はシステムで保証されるわけではなく、可能であればという制約の上での動作となっています。なお、本サンプルでも[SECONDACTIVITYを別ウィンドウで起動]ボタンにてこの動作を実装しています*。

*正直なところ自身のアプリと他のアプリをマルチウィンドウで動かすことにはあまり利点を感じないかもしれませんが、自身のアプリ内で複数のActivityを隣に並べながら利用するというケースであれば便利な使い方があるかもしれません。

リスト7 分割領域に新たにActivityを起動(実習のリスト3(1))
fi ndViewById(R.id.launch_activity_new_window).setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
    Intent intent = new Intent(MainActivity.this,SecondActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT |Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
  }
});

まとめ

  • マルチウィンドウの種類には、画面分割モード、ピクチャーインピクチャーモード、フリーフォームモードがあります。
  • マルチウィンドウに表示しているActivity はonStart、onStopメソッドが呼ばれないことを考慮した実装が必要です。
  • マルチウィンドウを細かく設定するには、APIレベル24をターゲットSDKに指定する必要があります。

補講

フリーフォームモードを有効にする方法

 N Previewではadbコマンドを使用してフリーフォームモードに切り替えることができます。もしフリーフォームモードでアプリのテストをしたい際にはAPIレベル24のエミュレータでリスト8のコマンドを実行してください。

リスト8 フリーフォームモードを有効にするadbコマンド
adb shell
settings put global enable_freeform_support 1

 コマンドを実行したら一度OSを再起動します。エミュレータの場合はエミュレータを起動し直してください。フリーフォームが正しく適用されている場合は、オーバービュー画面に表示されるアプリのツールバー部分に専用のアイコンが追加されます(図11)。

図11 フリーフォームモードが有効時のオーバービュー画面
図11 フリーフォームモードが有効時のオーバービュー画面

 フリーフォームモードはマルチタスクの自由度が高く、ほぼPCのようなウィンドウ操作が可能になります(図12)。ただし、これらをうまく活用するにはディスプレイが大画面である必要があるため、今後もあまり利用する機会のないマルチウィンドウモードかもしれません。

図12 フリーフォームモード時のアプリ操作画面
図12 フリーフォームモード時のアプリ操作画面
ほんきで学ぶAndroidアプリ開発入門 第2版

Amazon   SEshop   その他

ほんきで学ぶAndroidアプリ開発入門 第2版
Android SDK 7/Android Studio 2.X対応

著者:株式会社Re:Kayo-System
発売日:2016年11月17日(木)
価格:3,024円(税込)

本書について

本書は、はじめてAndroidアプリを作成する開発者を対象とした入門書です。楽しみながら新機能をしっかり学べるミニアプリを元にLESSON形式で学べます。また練習問題が章末についていますので、学習効果を自分で確認できます。