{"record":{"id":"2965378871135c6e","repo":"termux/termux-app","slug":"1-s-requires-display-over-other-apps-permission","errorCode":null,"errorMessage":"%1$s requires \"Display over other apps\" permission to start activities and services from background on Android >= 10. Grants it from Android Settings -> Apps -> %1$s -> Advanced -> Draw over other apps. The permission name may be different on different devices, like on Xiaomi, its called \"Display pop-up windows while running in the background\", check https://dontkillmyapp.com for device specific issues.","messagePattern":"%1\\$s requires \"Display over other apps\" permission to start activities and services from background on Android >= 10\\. Grants it from Android Settings -> Apps -> %1\\$s -> Advanced -> Draw over other apps\\. The permission name may be different on different devices, like on Xiaomi, its called \"Display pop-up windows while running in the background\", check https://dontkillmyapp\\.com for device specific issues\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"termux-shared/src/main/java/com/termux/shared/shell/am/AmSocketServer.java","lineNumber":222,"sourceCode":"     * @param stderr The {@link StringBuilder} to set stderr in that is returned by the am command.\n     * @param checkDisplayOverAppsPermission Check if {@link Manifest.permission#SYSTEM_ALERT_WINDOW}\n     *                                       has been granted if running on Android `>= 10` and\n     *                                       starting activity or service.\n     * @return Returns the {@code error} if am command failed, otherwise {@code null}.\n     */\n    public static Error runAmCommand(@NonNull Context context,\n                                     String[] amCommandArray,\n                                     @NonNull StringBuilder stdout, @NonNull StringBuilder stderr,\n                                     boolean checkDisplayOverAppsPermission) {\n        try (ByteArrayOutputStream stdoutByteStream = new ByteArrayOutputStream();\n             PrintStream stdoutPrintStream = new PrintStream(stdoutByteStream);\n             ByteArrayOutputStream stderrByteStream = new ByteArrayOutputStream();\n             PrintStream stderrPrintStream = new PrintStream(stderrByteStream)) {\n\n            if (checkDisplayOverAppsPermission && amCommandArray.length >= 1 &&\n                (amCommandArray[0].equals(\"start\") || amCommandArray[0].equals(\"startservice\")) &&\n                !PermissionUtils.validateDisplayOverOtherAppsPermissionForPostAndroid10(context, true)) {\n                throw new IllegalStateException(context.getString(R.string.error_display_over_other_apps_permission_not_granted,\n                    PackageUtils.getAppNameForPackage(context)));\n            }\n\n            new Am(stdoutPrintStream, stderrPrintStream, (Application) context.getApplicationContext()).run(amCommandArray);\n\n            // Set stdout to value set by am command in stdoutPrintStream\n            stdoutPrintStream.flush();\n            stdout.append(stdoutByteStream.toString(StandardCharsets.UTF_8.name()));\n\n            // Set stderr to value set by am command in stderrPrintStream\n            stderrPrintStream.flush();\n            stderr.append(stderrByteStream.toString(StandardCharsets.UTF_8.name()));\n        } catch (Exception e) {\n            return AmSocketServerErrno.ERRNO_RUN_AM_COMMAND_FAILED_WITH_EXCEPTION.getError(e, Arrays.toString(amCommandArray), e.getMessage());\n        }\n\n        return null;\n    }","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/termux/termux-app/blob/3df69d1da197dd9bd71a3bafd902dffd720576b4/termux-shared/src/main/java/com/termux/shared/shell/am/AmSocketServer.java#L204-L240","documentation":"Thrown by AmSocketServer.runAmCommand when, on Android 10+, a 'start' or 'startservice' am subcommand is requested but the app lacks the SYSTEM_ALERT_WINDOW ('Display over other apps') permission. Starting activities/services from the background requires this permission on API 29+. The message is a localized resource string formatted with the app name.","triggerScenarios":"Calling runAmCommand with an amCommandArray whose first element is 'start' or 'startservice', checkDisplayOverAppsPermission=true, on Android >= 10, while Settings.canDrawOverOtherApps() returns false.","commonSituations":"Fresh install without granting the overlay permission; background service tries to launch an activity; OEM battery-optimizer/background-killer reset the permission; plugin app invoking am from background.","solutions":["Request the user to grant 'Display over other apps' via Settings (the message links to it).","Programmatically send the user to ACTION_MANAGE_OVERLAY_PERMISSION settings before issuing background start commands.","Pass checkDisplayOverAppsPermission=false only if you have verified another valid way to start from background (rare).","Check PermissionUtils.validateDisplayOverOtherAppsPermissionForPostAndroid10(context, false) before calling runAmCommand and degrade gracefully."],"exampleFix":"// before\nif (checkDisplayOverAppsPermission && ... &&\n    !PermissionUtils.validateDisplayOverOtherAppsPermissionForPostAndroid10(context, true)) {\n    throw new IllegalStateException(context.getString(R.string.error_display_over_other_apps_permission_not_granted, ...));\n}\n\n// after (pre-check + send user to settings instead of throwing blindly)\nif (checkDisplayOverAppsPermission && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q\n        && !Settings.canDrawOverOtherApps(context)) {\n    Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse(\"package:\" + context.getPackageName()));\n    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n    context.startActivity(i);\n    return Error.withErrno(...); // signal caller to retry after grant\n}","handlingStrategy":"validation","validationCode":"if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q\n        && (\"start\".equals(amCommandArray[0]) || \"startservice\".equals(amCommandArray[0]))\n        && !Settings.canDrawOverOtherApps(context)) {\n    // send user to settings instead of letting runAmCommand throw\n    Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,\n        Uri.parse(\"package:\" + context.getPackageName()));\n    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n    context.startActivity(i);\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    AmSocketServer.runAmCommand(context, cmd, stdout, stderr, true);\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Display over other apps\")) {\n        promptUserForOverlayPermission();\n    } else throw e;\n}","preventionTips":["Check Settings.canDrawOverOtherApps() before issuing background start commands on API 29+.","Guide the user to the overlay-permission settings screen proactively.","Be aware OEM battery/background killers may reset this permission."],"tags":["android-permission","background-execution","am-socket","termux"],"backgroundTag":null,"analyzedSha":"3df69d1da197dd9bd71a3bafd902dffd720576b4","analyzedAt":"2026-08-13T22:46:28.294Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}