Android Nのマルチウインドウ対応について調べて驚いたところ

  • 122
    いいね
  • 0
    コメント

驚いた所を太字にします。

動機

Google Developer Summit 2016:Android 知らなかったこと驚いたことメモで聞いた話はあったのですが具体的にはよくわかっていない部分などがとても多いので1つずつ何が必要か整理したいと思います。
http://qiita.com/takahirom/items/aa3cb6ff69958128e958
とりあえず今回はマルチウインドウです(通知とか他のものも調べていきたい)

マルチウインドウ

画面を2つに分割したりできる機能です。何が必要なのか見ていきましょう。

Activityが他のアプリからstartActivityForResultで起動する可能性がある場合、マルチウインドウに対応する必要がある

android:resizeableActivity="false"にしようが、画面回転に対応させないようにしようが、マルチウインドウ中のActivityからstartActivityForResultで起動されたActivityはマルチウインドウで表示(画面分割された状態で表示)されます。
例えばGoogle keepはURLのWebのリンクをstartActivityForResultで起動していたりします。
同じタスクの中で起動すると同じマルチウインドウの状態を引き継いで表示されるようです。つまり、IntentにFLAG_ACTIVITY_NEW_TASKなどのフラグをつけて起動されている場合は引き継いで表示されませんので、GooglePlayアプリからの起動は大丈夫のようです。
Preview版のバグだと思いたいのですが、 Pro-tip 5: Activities started by other apps must always support multi-window などと紹介されていたりするので、対応必須になると思われます。
こちらAndroid developers blogでも紹介されているようです。
これは暗黙的インテントで起動された場合でも必要になるので、とても影響が大きいものとなります。
他のアプリから起動される可能性があるアプリでは、マルチウインドウのテストが必須になってくるでしょう。

マルチウインドウに対応しない場合の挙動の整理

他のアプリから起動される場合は対応必須なのですが、対応しない場合について説明します。
以下の様な対応内容になります。

アプリのtargetSdkVersionがN以降であればAndroidManifestのActivityの要素で、android:resizeableActivity="false"で対応しないようになります。(何も記述しないデフォルトでは対応します)

アプリのtargetSdkVersionがNより前であればAndroidManifestのActivityの要素で、android:screenOrientation="portrait"などで画面の方向を固定すると対応しなくなります。(何も記述しないデフォルトでは対応します)
またはandroid:immersive="true"にすると対応しなくなくなるので、こちらも方法として検討しても良いと思います。

画面回転とtargetSdkVersionのマルチウインドウ対応については以下のようになるようです。

アプリのtargetSdkVersion < N N <= アプリのtaregetSdkVersion
画面回転対応している ○(予想外の動作が発生する場合があることをユーザーに警告するダイアログが表示)
画面回転対応していない △(他のActivityからstartされると表示される) ○(そのアプリのみの画面になったら、設定された縦などに戻る)

onStopでUIの更新を止めるようにする

onPauseが呼ばれても画面が表示されている可能性があるので動画の再生をとめるのはonStop、再開する場所はonStart
例えば、画面分割時に他のウインドウがタップされるとonPauseが呼ばれるので、ここで止めると画面が表示されているのに動画が止まったりするためです。

マルチウインドウの画面に対応するために

UI周辺ではActivityのContextを使う

ApplicationContextを利用するとAndroidにはウインドウの大きさなどに合わせたリソースを取得する仕組み(Altanative Resource)があるがそれがうまく動かない。
例えば、layout-sw600dp/などのディレクトリに、タブレットレイアウトを入れて、スマホのレイアウトを分けていた場合に、マルチウインドウ時のウインドウの大きさに合わせてレイアウトのリソースを取得できなかったりする。

Manifestでandroid:configChangesを使っている場合は自分でリソースを再ロードさせる必要がある

android:configChangesを設定していない場合は画面回転同様にActivityのインスタンスが再生成されるため、そのタイミングでリソースから取得し直すため、問題にならないが、android:configChangesを使っていると再生成されないため再ロードが必要になる。
例えば、values/とvalues-sw600dp/フォルダが有る場合、これまで切り替える必要がなかったが、この部分を自分でonConfigurationChanged()メソッドのタイミングで再ロードを行う必要がある

調べ方

Android Nのマルチウインドウのソースコードを追って見て行きたかったのですが、非公開になっている?部分が多くちゃんと見れませんでした。
例えばandroid-n-preview-2のタグのActivityのコードなのですが、inMultiWindow()などのメソッドがありません。
https://android.googlesource.com/platform/frameworks/base/+/android-n-preview-2/core/java/android/app/Activity.java

とりあえずドキュメントなどからわかることをまとめていきます。
新しいマルチウインドウ付近のソースコードを見れる方法を知っている方お教えください。

以下のGoogleのLan LakeさんがまとめているTipsに知らないことがたくさんあったので、それの内容がほとんどになってしまいました。
5 tips for preparing for Multi-Window in Android N
https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64#.jxq45cwlg

上記を見ながら、android-MultiWindowPlaygroundを動かしてみて驚いたところをまとめてみました。
https://github.com/googlesamples/android-MultiWindowPlayground

参考

動作の変更点(日本語)
http://developer.android.com/intl/ja/preview/behavior-changes.html
Behavior Changes(英語)
http://developer.android.com/preview/behavior-changes.html

デベロッパー向けAndroid N
http://developer.android.com/intl/ja/preview/api-overview.html

マルチウインドウのサポート
http://developer.android.com/preview/features/multi-window.html

Google developer summitのスライド
http://yaraki.github.io/slides/gds-2016q2/index.html#1

5 tips for preparing for Multi-Window in Android N
https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64#.jxq45cwlg

"app targeting N and using android:screenOrientation allow multi-window mode."
https://code.google.com/p/android/issues/detail?id=205041