Skip to content
OhMyDitzzyPublic

About

App to change resolution without root.

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Scalara logo

Scalara

A rootless Android screen resolution & DPI changer.

CI Release License: Apache 2.0 Latest release
minSdk 24 Java 17 Material 3 Views Open issues

Scalara changes your Android device's display resolution and density (DPI) without root, using the WRITE_SECURE_SETTINGS permission and the same hidden WindowManager APIs Android itself uses behind adb shell wm size / wm density. No root, no persistent PC connection, no reboot — grant the permission once (via ADB or Shizuku) and Scalara does the rest, entirely on-device.

How it works

Android exposes a way to override the display's rendered size and density (IWindowManager.setForcedDisplaySize / setForcedDisplayDensityForUser, the exact mechanism behind adb shell wm size and wm density) without requiring root. Scalara reaches this hidden API via reflection (DisplayResolutionController), the same approach the shell command itself uses internally.

The catch: calling it from a third-party app requires the WRITE_SECURE_SETTINGS permission, which has a signature|privileged protection level — it can never be granted through the normal runtime permission dialog. Scalara supports two ways to grant it once, up front, during first-run setup:

Option A — ADB. Connect your device to a computer and run:

adb shell pm grant id.ditzzy.scalara android.permission.WRITE_SECURE_SETTINGS

Option B — Shizuku. If you'd rather not type an ADB command yourself, Shizuku gives Scalara the same permission through a privileged, on-device broker instead. Once Shizuku itself is running (via its own one-time ADB/wireless-debugging/root activation), Scalara binds a small privileged helper service (MyUserService, launched through Shizuku's bindUserService API) that runs pm grant … WRITE_SECURE_SETTINGS on your behalf, on-device — no typing ADB commands, no computer needed for this step. The setup wizard (SetupActivity) walks through requesting the Shizuku permission and triggering this grant with a couple of taps.

Shizuku's role ends there. pm grant is a one-shot call — Scalara binds the helper service, runs it, and unbinds immediately (see ShizukuManager). The resulting WRITE_SECURE_SETTINGS grant is tracked by Android's own PackageManager, the same place it'd live had you used Option A, so it is not contingent on Shizuku staying installed, active, or authorized for Scalara afterward. Disabling the Shizuku service or removing Scalara's access from the Shizuku app does not revoke it.

Either way, once granted:

  • Scalara can change resolution and density directly, instantly, without root and without a persistent ADB/computer connection.
  • The grant is checked every time the app resumes (MainActivity's permission guard), by asking PackageManager for WRITE_SECURE_SETTINGS directly — regardless of which option was used to grant it. If it's ever actually revoked — by the system or by pm revoke — Scalara detects it and routes you back into setup rather than failing silently mid-action.

Features

🖥️ Resolution & density control

  • Change screen resolution (width × height) and density (DPI) independently, applied instantly — no reboot.
  • Reset to default with one tap, restoring the device's real physical resolution and density at any time.
  • Read-only default resolution card on the home screen, always showing your device's true (unforced) resolution and DPI for reference.

🧪 "Try it out" — safe timed preview

  • Preview any resolution/DPI combination for a short window (default 10s, configurable 3–60s in Settings) before committing to it.
  • Runs as a foreground service (PreviewRevertService) with a live countdown notification, so it reliably reverts even if you leave the app, rotate the screen, or it gets backgrounded — a plain in-app timer couldn't guarantee that.
  • "Revert now" action right from the notification if you want to bail out early.

📌 Presets

  • Save named width/height/DPI combinations for instant reuse later.
  • Four independent actions per preset, matching real workflows: Apply (save + apply immediately), Try it out (preview only, nothing saved), Save (just save it), or apply/delete an existing one from its own options sheet.

⚠️ Dangerous-resolution guard

  • Before applying or previewing a value that deviates more than 50% from your device's default width, height, or DPI, Scalara shows a confirmation dialog first — the exact kind of change that can otherwise leave a device hard to see or navigate.
  • Toggleable in Settings, on by default.

🔒 Encrypted preset export/import

  • Export a single preset or your entire saved list to a password-protected .scl file, and import it back later or on another device.
  • Real encryption, not obfuscation: AES-256-GCM with a PBKDF2-HMAC-SHA256 key (600,000 iterations, per OWASP's current guidance) derived from your password and a random per-file salt. See Preset export format below.
  • Import supports merge (add to your existing presets) or replace (start fresh from the imported file), with a preview of what's inside before anything is committed.

Getting started

Prerequisites

  • Android Studio (recent stable) or the command line with JDK 17 if you want to build scalara locally
  • An Android device or emulator running API 24+
  • ADB (or Shizuku) to grant WRITE_SECURE_SETTINGS — see How it works

Build

./gradlew assembleDebug

The debug APK is written to app/build/outputs/apk/debug/.

Run tests & lint

./gradlew testDebugUnitTest
./gradlew lintDebug

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a PR, and check existing issues first.

Adding a translation

Scalara's in-app language picker (Settings → Language) never hardcodes which languages are available — a Gradle task (generateLocalesList, in app/build.gradle.kts) scans app/src/main/res/ at build time for values-<lang> directories and generates the picker's option list from whatever it finds. Currently shipped: 🇬🇧 English (values/, the default) and 🇮🇩 Bahasa Indonesia (values-in/).

To add a new language, copy app/src/main/res/values/strings.xml into a new app/src/main/res/values-<tag>/strings.xml (e.g. values-es/ for Spanish, values-pt-rBR/ for Brazilian Portuguese) and translate every string. That's it

License

Licensed under the Apache License 2.0. See also NOTICE.

About

App to change resolution without root.

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages