All articles

Tutorial

How to Lock Screen Orientation in an Android TWA

October 26, 2026 · 5 min read

When converting a Progressive Web App (PWA) to an Android application with a Trusted Web Activity (TWA), matching native layout expectations is critical. For utilities like calculators, standard SaaS dashboards, and forms, keeping the application locked in portrait mode provides a consistent interface. Conversely, for games, media players, and data visualisations, forcing landscape layout is necessary to keep visual components intact.

Without a defined orientation lock, rotation behaves dynamically based on device sensors. This can disrupt your user interface if your web layout is not fully fluid, or if rotation causes unwanted state reloads. Locking screen orientation inside a TWA can be achieved through two distinct vectors: the Web App Manifest and the native Android Manifest. Combining these strategies guarantees a stable layout from the moment the app icon is tapped.

Defining Orientation in the Web App Manifest

The first line of defence is your web-standard configurations. The Web App Manifest file allows you to define a default orientation viewport. When modern Android devices boot your TWA, the Chrome web engine reads this manifest configuration and applies the rendering rule immediately.

To configure this, open your web app manifest file (typically manifest.json or site.webmanifest) and add or update the orientation property. Below is an example block showing how to enforce portrait orientation:

{
  "name": "SaaS Tool",
  "short_name": "SaaS",
  "start_url": "/",
  "display": "standalone",
  "orientation": "portrait"
}

The specification supports several key values depending on your target viewport needs:

  • portrait: Locks the viewport to portrait-primary or portrait-secondary based on device rotation.
  • landscape: Locks the viewport to landscape layout.
  • portrait-primary: Enforces a strict upright portrait view, ignoring upside-down rotations.
  • landscape-primary: Enforces standard widescreen rotation.
  • any: Allows fluid, unrestricted 360-degree rotation.

Overriding Orientation in the Native Android Manifest

While the Web App Manifest works well once the browser engine is active, relying solely on web files can cause a momentary glitch during cold boot. When a user launches your app, there is a brief initialization window where the native Android wrapper is loading Chrome. If the device is held horizontally, the native splash screen might render in landscape mode, only to snap back to portrait once the Web App Manifest is parsed. This looks unpolished.

To fix this, you should lock the orientation within the native host wrapper. This is defined in the AndroidManifest.xml file within your Android project build files. The compiler maps these instructions directly to the operating system before any web content is requested.

Locate the main Activity block (usually containing the launcher intent) inside the manifest XML and append the android:screenOrientation property. This tells the system how to draw the container window immediately on startup:

<activity
  android:name=".MainActivity"
  android:screenOrientation="portrait"
  android:configChanges="orientation|screenSize">
  ...
</activity>

By listing both screenOrientation and configChanges, you instruct the Android system to let your app control orientation transitions internally, preventing unnecessary activity teardowns and re-creations during physical device rotations.

Dynamic Control via JavaScript

If your application requires dynamic switching—such as running in portrait for navigation menus, but switching to landscape when a user views a full-screen video—you can utilise the Screen Orientation API inside your frontend JavaScript code. This API allows your web code to request a lock state at runtime.

To implement runtime locking, call the lock method on the global window navigation space. Because this returns a promise, you must catch errors in cases where the system rejects the request due to user interaction rules.

function forceLandscape() {
  if (screen.orientation && screen.orientation.lock) {
    screen.orientation.lock('landscape').catch(function(error) {
      console.error('Orientation lock rejected: ', error);
    });
  }
}

To return to normal system rotation rules when the user closes the video, call the unlock method:

function releaseOrientation() {
  if (screen.orientation && screen.orientation.unlock) {
    screen.orientation.unlock();
  }
}

Comparing Manifest vs Android Level Settings

Using the correct implementation layer ensures smooth performance. Below is a comparison of how different orientation methods affect your user experience:

Implementation LayerBoot StabilityRuntime FlexibilityBest Used For
Web ManifestMediumLowStandard, single-layout web apps with basic views.
Android ManifestHighNone (static)Apps that must never rotate, preserving splash layout.
JavaScript APINoneHighMedia players, presentations, and games.

For optimal results when publishing to Google Play, hard-code the native Android Manifest orientation setting to match your Web App Manifest. This prevents visual shifting during startup and ensures your layout looks professional and native from the first frame.

Ready to ship your Android app?

Paste your PWA URL, get a signed APK and a Google Play ready AAB in minutes.

Build my app