← Back to posts

Modernizing Android UX: High Refresh Rates & App Shortcuts

How to request 90Hz/120Hz rendering and implement static deep-linked app shortcuts to improve mobile application usability.

Case Snapshot

Situation

An Android application felt sluggish on modern flagship devices and lacked quick-access entry points for power users.

Issue

The app was locked to standard 60Hz rendering, causing sub-optimal scrolling experiences on devices capable of 90Hz or 120Hz. Additionally, users had to navigate through multiple screens to perform frequent actions.

Solution

Detected 90Hz+ display modes and configured window post-processing preferences for smoother rendering, then implemented static XML-based app shortcuts routed via deep links.

Used In

Used to modernize an Android mobile application built with Jetpack Compose.

Impact

Significantly improved perceived performance and fluidity, while reducing friction for core user journeys.

Situation

As mobile hardware advances, user expectations for fluidity and accessibility increase. An Android application was functioning correctly but felt distinctly “last generation.”

Two main issues were identified:

  1. Scrolling felt jittery: Despite running on modern flagship devices capable of 120Hz refresh rates, the app was rendering at the baseline 60Hz.
  2. High friction for frequent tasks: Power users wanting to quickly add a record or view a specific dashboard had to launch the app, wait for the home screen, and navigate the UI manually.

Implementing High Refresh Rate Support

Historically, Android managed refresh rates strictly at the system level. However, newer APIs allow applications to request higher rendering priorities.

The Technical Fix

To request 90Hz/120Hz support, a utility manager was created to configure refresh-rate-related window/display settings at Activity launch.

The implementation relies on Android 11+ (API 30+) / Android 12+ (API 31+) APIs:

// Example concept for enabling high refresh rate
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    // Detect the best supported display mode (90Hz+), and let the system choose it
    // (preferredDisplayModeId often requires system-level privileges in practice)
    val modes = activity.display?.supportedModes.orEmpty()
    val best = modes.filter { it.refreshRate >= 90f }.maxByOrNull { it.refreshRate }
    android.util.Log.d("RefreshRate", "Best available mode: ${best?.refreshRate}Hz")
}

// For Android 12+ (API 31+), configure post-processing preference
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    activity.window.attributes.preferMinimalPostProcessing = false
}

By configuring post-processing preference and ensuring window rendering is optimized (e.g., hardware acceleration), high refresh rate devices can render smoother Compose scrolling and animations when the system selects a 90Hz/120Hz mode.

Implementing Static App Shortcuts

To solve the friction issue, Android’s App Shortcuts feature was utilized. This allows users to long-press the application icon on their home screen to reveal a quick-action menu.

Static shortcuts were defined in an XML resource file (shortcuts.xml), pointing to specific deep links rather than just launching an Activity.

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
    <shortcut
        android:shortcutId="add_record"
        android:enabled="true"
        android:icon="@drawable/ic_shortcut_add"
        android:shortcutShortLabel="@string/shortcut_add_record">
        <intent
            android:action="android.intent.action.VIEW"
            android:data="myapp://add-record" />
    </shortcut>
</shortcuts>

Routing the Action

When a user taps the shortcut, the OS fires the intent with the associated deep link (myapp://add-record). The main Activity catches this intent and passes the URI directly into the application’s navigation router (e.g., Jetpack Compose Navigation), immediately jumping the user exactly where they need to be.

This combination of rendering performance and rapid accessibility transformed the application from feeling like a basic utility to a premium, deeply integrated system citizen.

Architecture Diagram

Modernizing Android UX: High Refresh Rates & App Shortcuts execution diagram

This diagram supports Modernizing Android UX: High Refresh Rates & App Shortcuts and highlights where controls, validation, and ownership boundaries sit in the workflow.

Post-Specific Engineering Lens

For this post, the primary objective is: Improve perceived responsiveness and reduce tap-to-task friction.

Implementation decisions for this case

  • Chose a staged approach centered on android to avoid high-blast-radius rollouts.
  • Used ux checkpoints to make regressions observable before full rollout.
  • Treated performance documentation as part of delivery, not a post-task artifact.

Practical command path

These are representative execution checkpoints relevant to this post:

adb shell dumpsys SurfaceFlinger | findstr refresh
adb shell am start -a android.intent.action.VIEW -d "myapp://..."
adb shell dumpsys gfxinfo <package>

Validation Matrix

Validation goalWhat to baselineWhat confirms success
Functional stabilityframe pacing, startup path, and interaction latencycritical user flows complete without navigation regressions
Operational safetyrollback ownership + change windowperformance traces show smoother frame delivery
Production readinessmonitoring visibility and handoff notesshortcut/deeplink paths remain deterministic across app states

Failure Modes and Mitigations

Failure modeWhy it appears in this type of workMitigation used in this post pattern
Device-specific behaviorUX differs across OEM implementationsTest across at least one mid and one high-tier device
Navigation edge caseDeep links break when app state is partialNormalize entry routing through a single handler
Performance regressionSmall UI changes impact frame pacingTrack frame timing in CI/perf checks

Recruiter-Readable Impact Summary

  • Scope: improve mobile UX without introducing lifecycle regressions.
  • Execution quality: guarded by staged checks and explicit rollback triggers.
  • Outcome signal: repeatable implementation that can be handed over without hidden steps.