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

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

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

## マルチウインドウ
画面を２つに分割したりできる機能です。何が必要なのか見ていきましょう。


### **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](https://medium.com/google-developers/5-tips-for-preparing-for-multi-window-in-android-n-7bed803dda64#.jxq45cwlg) などと紹介されていたりするので、対応必須になると思われます。
こちら[Android developers blog](http://android-developers.blogspot.jp/2016/05/designing-for-multi-window.html?m=1)でも紹介されているようです。
これは暗黙的インテントで起動された場合でも必要になるので、とても影響が大きいものとなります。
他のアプリから起動される可能性があるアプリでは、マルチウインドウのテストが必須になってくるでしょう。

### マルチウインドウに対応しない場合の挙動の整理
他のアプリから起動される場合は対応必須なのですが、対応しない場合について説明します。
以下の様な対応内容になります。

アプリの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