はじめに

こちらの記事は「Android 16における大画面端末の固定UI廃止とアプリ開発者が対応すべきポイント」の動作確認にフォーカスした記事になります。

上記記事の結論としては16以前からも大画面デバイスの画面回転を意識しなければならないということで、こちらの記事単体でも完結する内容になっていますが、お時間がありましたら併せて読んで頂ければと思います。

動作確認

大きなポイントとして以下を確認しつつ、検証としてAndroidViewとComposeViewで挙動に違いがあるのかも見ていきます。

  • manifestのscreenOrientationでの画面固定
  • Activity#setOrientationでの画面固定
  • manifestのconfigChangesでのアクティビティ再生成無効化

検証デバイスはPixel9ProFoldデバイスのエミュレーターを使用します。
APIバージョンはAndroid15(APILevel:35)、Android16 beta2(APILevel:36)をインストールしました。

確認用アプリについて

簡単な確認用アプリとして、画面固定の宣言やViewの書き方が異なるActivity4画面と、 それぞれの画面に変更可能かつ再生成で破棄されるアイコン(左)、再生成で破棄されないアイコン(右)を用意しました。 実装内容については、簡易的なアプリなのと全て書いてしまうと長くなってしまうので各画面で設定している内容を記載します。

FirstActivity

観点:manifestでの画面固定宣言を指定している時の挙動を確認する。

  • manifestにandroid:screenOrientation="portrait"を指定
  • ComposeView
    • 左のアイコンのリソースはrememberで保持:Activity再生成の確認
    • 右のアイコンのリソースはrememberSaveableで保持:Activity再生成の確認
    • 遷移ボタンは横いっぱい均一に表示する:レイアウト可変の確認

<!--AndroidManifest.xml--->
<activity
  android:name=".FirstActivity"
  android:exported="true"
  android:label="@string/app_name"
  android:screenOrientation="portrait"
...

Android 15、16(beta2)どちらも同じ結果のため、動画はアスペクト比設定「アプリのデフォルト」「全画面」を比較しています。
(以降他Activityも同様)

SecondActivity

観点:オプション未指定の時の挙動を確認する。

  • 画面固定系のオプションを設定しない
  • ComposeView(FirstActivityと同様の構成)

(アスペクト比に関わらず同じ結果なのでアプリのデフォルトのみ載せています)
オプション指定してないので再生成もされ、画面向きの全画面レイアウトになりました。

ThirdActivity

観点:configChangesでアクティビティの再生成を防いでいる時の挙動を確認する。

  • manifestにandroid:screenOrientation="portrait"、 android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"を指定
  • ComposeView(FirstActivity同様)
<!--AndroidManifest.xml-->
<activity
  android:name=".ThirdActivity"
  android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"
  android:exported="true"
  android:screenOrientation="portrait"
...

Android15、Android16ともにconfigChangesは有効のため、再生成はされませんでした。
レイアウトについてはFirstActivity同様の結果です。

FourthActivity

観点:Activityで画面固定をしている時の挙動を確認する。

  • Activity#setRequestedOrientationでSCREEN_ORIENTATION_PORTRAITを指定
  • Fragment+AndroidView(XMLレイアウト)
    • 左のアイコンのリソースはActivityで保持(Bundleへの保存も行わない):Activity再生成の確認
    • 右のアイコンのリソースはViewModelで保持:Activity再生成の確認
    • 遷移ボタンは横いっぱい均一に表示する:レイアウト可変の確認
// FourthActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
  requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
  ...

FirstActivityと同様の結果になりました。
予想通り、AndroidLayout、ComposeViewで画面の書き方や保存の方法に違いはありますが、挙動に差はなかったです。

また、Android16対応ポイントの記事でも言及しましたがアプリの向きの制限が無視される場合、Activity#setRequestedOrientationを呼び出せば画面固定できそうな言い回しに見える文章がありながら、実際は固定されないのはちょっとややこしいですね。
この挙動は互換モードの導入からですので実質的に12以降の大画面デバイスは画面回転を避けられなくなっていたということになります。

Android 12(API レベル 31)以降では、デバイス メーカーはアプリが指定した画面の向きの制限を無視し、代わりに互換モードを適用できるようになりました。たとえば、折りたたみ式デバイスは、デバイスの横向きのタブレット サイズの内部画面でアクティビティが表示される場合、アクティビティの android:screenOrientation=”portrait” 設定を無視することがあります。
アプリの向きの制限が無視される場合、アプリは Activity#setRequestedOrientation() を呼び出して画面の向きをプログラムで設定できます。アプリが構成の変更を処理していない場合、この呼び出しによりアプリの再起動がトリガーされます(構成の変更を処理するをご覧ください)。

おわりに

結論としてAndroid16以前から、大画面デバイスでの画面回転はどのオプションでも行われ、またManifestにconfigChangesを付与した画面以外は再生成が行われました。
画面比率に関しては「アプリのデフォルト」になっていればAndroid16でも互換モードでアプリが設定した画面向きの比率で表示してくれますが、ユーザーは「全画面」で無効にすることもできるためデフォルト前提で考えない方が良さそうです。



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる