RORK LABEN
EVENT — 本日9月9日、Apple が「Surprise and Shine」と題したイベントを開きます。日本時間では9月10日の未明2時からですEXPECT — iPhone 18 Pro と Pro Max、折りたたみ機、2nm プロセスの A20 Pro チップ、そして iOS 27 以下の配信日発表が見込まれていますWAIT — この記事を書いている時点ではまだ開催前です。噂の段階で書いたものと発表後に書いたものが混ざると、読む側には区別がつきませんMAX — Rork Max がネイティブ Swift を生成する以上、Apple の動きは他人事ではありません。標準の Rork は React Native、という線引きは繰り返し確認したいところですSIMULATOR — Rork Max はクラウド上の Mac でコンパイルし、ブラウザ内で動くストリーミングの iOS シミュレータで確認できます。Xcode も Mac の実機も要りませんSEASON — OS が新しくなる時期は、自動生成の足場がいちばん揺れます。便利さを謳う記事ほど、この揺れに触れないと不誠実になると感じていますEVENT — 本日9月9日、Apple が「Surprise and Shine」と題したイベントを開きます。日本時間では9月10日の未明2時からですEXPECT — iPhone 18 Pro と Pro Max、折りたたみ機、2nm プロセスの A20 Pro チップ、そして iOS 27 以下の配信日発表が見込まれていますWAIT — この記事を書いている時点ではまだ開催前です。噂の段階で書いたものと発表後に書いたものが混ざると、読む側には区別がつきませんMAX — Rork Max がネイティブ Swift を生成する以上、Apple の動きは他人事ではありません。標準の Rork は React Native、という線引きは繰り返し確認したいところですSIMULATOR — Rork Max はクラウド上の Mac でコンパイルし、ブラウザ内で動くストリーミングの iOS シミュレータで確認できます。Xcode も Mac の実機も要りませんSEASON — OS が新しくなる時期は、自動生成の足場がいちばん揺れます。便利さを謳う記事ほど、この揺れに触れないと不誠実になると感じています
記事一覧/アプリ開発
アプリ開発/2026-08-26中級

タブレットで縦固定が外れる Android 16 の変更と、Expo 側に用意されていない逃げ道

targetSdkVersion 36 では、sw600dp 以上の画面で screenOrientation が無視されます。app.json の orientation では戻せないこと、オプトアウトのプロパティが何を戻して何を戻さないかを、手元で確かめた出力とあわせて整理しました。

Android 164Expo203config plugin6AndroidManifest2Google Play34

プレミアム記事

タブレットのエミュレータを起動したのは、8月31日まで残り5日という数字を見た後でした。

個人開発で運用している壁紙アプリは、どれも縦向きの一覧を前提に組んでいます。Play の期限に合わせて targetSdkVersion を 36 に上げる作業そのものは、先に済ませていました。残っていたのは、上げた後に何が変わるかの確認です。

エミュレータを横に倒したら、縦固定にしていたはずの一覧が横に広がりました。マニフェストは触っていません。

無視されるのは、この8つの値です

Android 16(API レベル 36)を対象にしたアプリでは、最小幅が 600dp 以上のディスプレイで、向き・アスペクト比・リサイズ可否の指定が無視されます。対象になるのはタブレット、大画面折りたたみ端末の内側ディスプレイ、そしてデスクトップウィンドウです。

無視される指定は次のとおりです。

属性・API無視される値
screenOrientationportrait / landscape / reversePortrait / reverseLandscape / sensorPortrait / sensorLandscape / userPortrait / userLandscape
resizeableActivityすべて
minAspectRatioすべて
maxAspectRatioすべて
setRequestedOrientation()screenOrientation と同じ8値

この表を読むとき、私が最初に見落としていたのは「載っていない値」のほうでした。unspecifiedlockednosensorsensoruserfullSensor は、無視される値の一覧に入っていません。

例外もあります。sw600dp 未満の画面、つまり大半のスマートフォンと折りたたみ端末の外側ディスプレイは対象外です。android:appCategory がゲームのアプリも対象から外れます。それから、ユーザーが端末側のアスペクト比設定で従来の挙動を選んだ場合も除かれます。

つまり「スマートフォンで確認したから大丈夫」は成立しません。私がエミュレータを開くまで気づけなかったのは、まさにこの理由でした。

なお、同じ Android 16 でも予測型「戻る」の既定変更はこれとは別の仕組みで、オプトアウトの書き方も違います。そちらはAndroid 16 の予測型「戻る」の判断で扱いました。混ぜて考えると、どちらの対処も中途半端になります。

手元のプロジェクトが該当するかを、実機の前に判定する

タブレットを買いに行く前に、まず設定値を見ます。Rork や Expo のプロジェクトでは、向きの指定が入る場所が2か所あります。app.json と、prebuild 後の AndroidManifest.xml です。

この2つは食い違うことがあります。prebuild の後にマニフェストを手で直していると、app.json を読んでも実体が分かりません。逆に、マニフェストを消して再生成する運用なら app.json が正です。

両方を見て、実際に効いている値を出す小さなスクリプトを書きました。

// check-orientation.mjs — プロジェクトルートで node check-orientation.mjs
import { readFileSync, existsSync } from 'node:fs';
 
// Android 16 (API 36) が sw600dp 以上で無視する screenOrientation の値
const IGNORED = new Set([
  'portrait', 'landscape',
  'reversePortrait', 'reverseLandscape',
  'sensorPortrait', 'sensorLandscape',
  'userPortrait', 'userLandscape',
]);
 
function fromAppJson(path) {
  if (!existsSync(path)) return null;
  const json = JSON.parse(readFileSync(path, 'utf8'));
  const cfg = json.expo ?? json;
  // app.json の orientation は 'default' | 'portrait' | 'landscape' の3値のみ
  // 'default' は android:screenOrientation="unspecified" に落ちる
  const o = cfg.orientation;
  if (!o) return null;
  return o === 'default' ? 'unspecified' : o;
}
 
function fromManifest(path) {
  if (!existsSync(path)) return null;
  const xml = readFileSync(path, 'utf8');
  // prebuild 後に手で書き換えている場合はこちらが実体
  const m = xml.match(/android:screenOrientation="([^"]+)"/);
  return m ? m[1] : null;
}
 
const manifestPath = 'android/app/src/main/AndroidManifest.xml';
const manifestValue = fromManifest(manifestPath);
const appJsonValue = fromAppJson('app.json') ?? fromAppJson('app.config.json');
const effective = manifestValue ?? appJsonValue ?? 'unspecified(未指定)';
const source = manifestValue ? manifestPath : (appJsonValue ? 'app.json' : 'どちらにも指定なし');
 
console.log(`screenOrientation = ${effective}  (source: ${source})`);
 
if (manifestValue && appJsonValue && manifestValue !== appJsonValue) {
  console.log(`⚠️ app.json(${appJsonValue}) と Manifest(${manifestValue}) が食い違っています`);
}
 
if (IGNORED.has(effective)) {
  console.log('❌ sw600dp 以上の画面ではこの指定は無視されます');
  process.exitCode = 1;
} else {
  console.log('✅ 無視対象の値ではありません');
}

app.json"orientation": "portrait" だけがある状態で走らせると、次のように出ます。

screenOrientation = portrait  (source: app.json)
❌ sw600dp 以上の画面ではこの指定は無視されます

prebuild 済みのプロジェクトで、マニフェスト側が unspecified に書き換わっている場合はこうなります。

screenOrientation = unspecified  (source: android/app/src/main/AndroidManifest.xml)
⚠️ app.json(portrait) と Manifest(unspecified) が食い違っています
✅ 無視対象の値ではありません

終了コードを返すようにしてあるので、複数のアプリを抱えている場合はディレクトリを回して一括で確認できます。私は手元のリポジトリを一巡させて、対象になるものを先に洗い出しました。実機を触るのは、その後です。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
自分のプロジェクトが Android 16 の向き解除の対象になるかを、タブレット実機を用意せずに判定できるようになる
オプトアウトのプロパティを書いても縦固定は戻らないことを、ストア提出の前に把握できるようになる
app.json で足りない設定を config plugin へ移すとき、property と meta-data の取り違えを避けられるようになる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-08-30
targetSdk を 36 にした後、依存ライブラリのどこを見るか
依存ライブラリの AndroidManifest を実際に6本開いて数えました。targetSdkVersion は1本も書かれておらず、代わりに12個の権限が入ってきます。提出前に何を見るべきかの整理です。
アプリ開発2026-08-23
targetSdk を 36 に上げたら 16 KB の警告が出ました。この2つは別の期限です
対象 API レベル36 の8月31日と、16 KB メモリページサイズの2027年2月1日は別の条件です。NDK を入れずに手元の AAB を検査する方法と、LOAD のずれと zip 境界のずれで直し方が変わることを、実際の出力とあわせて整理しました。
アプリ開発2026-08-18
Rork のプロジェクトで targetSdkVersion 36 を通すまでに直した3か所
app.json に targetSdkVersion 36 と書いてあるのに、ビルドが読んでいた値は 35 でした。実効値を報告するスクリプトと、引き上げ・更新停止・延長申請の三択の分け方を残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます