An Android application that provides a home screen widget to quickly toggle the screen's display size (zoom level) between the system default and a magnified setting.
- A simple home screen widget with a single button.
- Tapping the widget will cycle between the phone's default display size and a larger, "zoomed-in" display size.
- The app itself will contain a simple instruction screen explaining how to grant the required permission.
- Language: Kotlin
- UI Framework:
- Widget: Standard Android
AppWidgetProviderwithRemoteViews. - Instruction Screen: Jetpack Compose.
- Widget: Standard Android
- Architecture: A
BroadcastReceiverwill handle widget taps to execute the zoom change.
To change the screen zoom, the app needs the WRITE_SECURE_SETTINGS permission. This is a highly protected permission.
- You cannot grant this permission from your phone directly.
- You will need to connect your phone to a computer and run a single command using the Android Debug Bridge (adb).
The main screen of the app will detect if the permission is granted and will show you the exact adb command you need to run. This is a one-time setup step.
Alternatively, this repository includes automated setup scripts in the scripts/ directory:
scripts/grant_permission.py: Automatically findsadbon your system and grants theWRITE_SECURE_SETTINGSpermission to the connected device.scripts/install_latest.py: Automatically downloads the latest release APK from GitHub, uninstalls any conflicting versions, installs the new APK, and grants the required permissions usinggrant_permission.py.
- Project Setup: Create a new, empty Android project configured for Kotlin and Jetpack Compose.
- Instruction Screen: Build a simple UI that checks for the
WRITE_SECURE_SETTINGSpermission and displays the necessaryadbcommand if it's missing. - Widget UI: Design a basic widget layout with a button and an icon.
- Widget Logic: Implement the
AppWidgetProviderto place the widget on the home screen. - Zoom Logic: Implement the density change via reflection (see Technical Details below).
- State Tracking: The widget will change its icon to indicate whether the zoom is "on" or "off".
Changing the system display density from a third-party app process is heavily restricted in modern Android versions. The working solution uses a combination of techniques:
Settings.Secure.display_density_forced: Writing to this setting requires theWRITE_SECURE_SETTINGSpermission. While the app can successfully write to the setting, the change does not take effect immediately. It only acts as persistence for the next reboot.wm densityvia Shell: ExecutingRuntime.getRuntime().exec("wm density ...")from an app process fails on many devices (like Samsung) because SELinux policies block third-party app processes from accessing the WindowManager service.- Hidden APIs: The Android framework's internal method to change density is
IWindowManager.setForcedDisplayDensityForUser. However, this is a "hidden API" restricted by Android (max-target-o).
To bypass these restrictions and apply the density change immediately without rebooting or root access:
targetSdkDownshift: The app'stargetSdkVersioninbuild.gradle.ktsis intentionally set to26(Android O). Because theIWindowManagerreflection call is restricted withmax-target-o, lowering the target SDK to 26 lifts the hidden API restriction, allowing our app to use it.- IWindowManager Reflection: We use Java Reflection to get the
IWindowManagerbinder interface and callsetForcedDisplayDensityForUser(0, dpi, userId). This is the exact same method that thewm densitycommand calls internally, but we execute it directly from the app process. - User ID Resolution: The
userIdparameter cannot be-2(USER_CURRENT) because that requires the system-levelINTERACT_ACROSS_USERS_FULLpermission. Instead, we calculate the actual user ID from the app's UID (Process.myUid() / 100000), which allows the call to succeed for the current user. - WRITE_SECURE_SETTINGS: The WindowManager still checks if the caller has the
WRITE_SECURE_SETTINGSpermission, which the app possesses thanks to the one-time ADB grant.