rn-app-exit
v1.1.0
Published
Exit a React Native app — or send it to the background without killing it. TurboModule (New Architecture) and Old Architecture, in Kotlin and Objective-C++.
Maintainers
Readme
rn-app-exit
Exit or background your React Native app — with full New Architecture (TurboModules) support, written in Kotlin and Objective-C++.
Why this package?
Most apps eventually need one of two things:
- Hard exit — a logout button, a kiosk reset, a session wipe that kills the process
- Background — a "minimize" button, a back-to-home UX without killing the process
react-native-exit-app is the established package for the first case, and it is a good one — since v2.0.0 (June 2023) it supports the New Architecture on both platforms. If a hard exit is all you need, use it.
rn-app-exit exists for the second case. Its entire published API is exitApp() — there is no way to send an app to the background with it. That is the gap this package fills.
Features
Compared against react-native-exit-app v2.0.0, honestly — including where it is ahead:
| | react-native-exit-app | rn-app-exit |
|---|---|---|
| Exit app | ✅ | ✅ |
| Send to background | ❌ | ✅ |
| Unified exit({ background }) | ❌ | ✅ |
| Capability flags (isAvailable, isBackgroundSupported) | ❌ | ✅ |
| Safe import — no crash when the native module is absent | ❌ | ✅ |
| New Architecture (TurboModules) | ✅ | ✅ Android · ⚠️ iOS via interop |
| iOS implements the codegen spec (getTurboModule:) | ✅ | ❌ (see New Architecture) |
| Old Architecture | ✅ | ✅ |
| Android language | Java | Kotlin |
| Automated tests + CI | ❌ | ✅ |
| Min React Native | 0.60 | 0.68 |
Pick react-native-exit-app if you only need a hard exit and want the most widely used option — it is more battle-tested, and its iOS TurboModule implementation is more complete than this one's.
Pick rn-app-exit if you need to background an app rather than kill it, want the capability flags, or want a package that does not throw at import time when the native side is missing.
Installation
npm install rn-app-exitiOS
cd ios && pod installAndroid
No additional steps — auto-linked via React Native's autolinking.
Usage
import AppExit from 'rn-app-exit';Hard exit (kill the process)
AppExit.exitApp();Terminates the app process immediately. The app is removed from recents on Android. On iOS, use this only for non-App-Store builds (kiosks, enterprise, dev tooling) — Apple's HIG discourages exit() in consumer App Store apps.
Send to background (keep process alive)
AppExit.sendToBackground();Moves the app to the background without terminating. The process stays alive in memory — the user can resume from the app switcher exactly where they left off.
- Android: calls
moveTaskToBack(true)— native OS feature, fully reliable - iOS: suspends via a private
UIApplicationselector — works on current iOS versions, but is not public API (see iOS notes)
Unified API
// Hard exit (default)
AppExit.exit();
// Background instead of kill
AppExit.exit({ background: true });The exit() method is the recommended API for most use cases. Pass { background: true } to move to background instead of killing.
Check capability at runtime
// Is the native module linked at all? False on web, in Expo Go, or when the
// app was not rebuilt after install. Never throws.
if (!AppExit.isAvailable) return;
if (AppExit.isBackgroundSupported) {
// Android — public OS API, reliable.
AppExit.sendToBackground();
} else {
// iOS — sendToBackground() still works, but via private API. Decide
// explicitly whether you want that in a store build.
AppExit.sendToBackground();
}isBackgroundSupported answers "is this a sanctioned API here?", not "will the call do something?" — on iOS it is false and the call still works.
API Reference
AppExit.exit(options?)
| Parameter | Type | Default | Description |
|---|---|---|---|
| options.background | boolean | false | When true, sends to background instead of killing |
AppExit.exitApp()
Kills the process.
| Platform | Implementation |
|---|---|
| Android | activity.finish() + Process.killProcess(myPid()) |
| iOS | exit(0) |
iOS warning: Apple's App Store review guidelines discourage programmatic exit. Prefer
sendToBackground()in consumer iOS apps.
AppExit.sendToBackground()
Moves the app to the background without terminating the process.
| Platform | Implementation |
|---|---|
| Android | activity.moveTaskToBack(true) |
| iOS | UIApplication suspend selector |
AppExit.isAvailable
boolean — whether the native module resolved. false on web, in Expo Go, or in a build where the native side was not rebuilt. Reading it never throws, so it is safe to branch on before any other call.
AppExit.isBackgroundSupported
boolean — true on Android, false on iOS and wherever the module is unavailable.
On Android, moveTaskToBack is a first-class OS feature. On iOS, backgrounding is managed by the OS and there is no public API — the package uses a best-effort approach that works on current iOS versions but is not a documented public API.
TypeScript
Full TypeScript support is included. The exported types are:
type AppExitOptions = {
background?: boolean;
};The Spec interface for the native module is also exported from rn-app-exit/src/NativeAppExit if you need it.
Platform notes
Android
All three methods work as expected on Android API 21+. sendToBackground() behaves exactly like pressing the Home button — the task moves to the back stack and the process continues running.
iOS
Apple does not provide a public API for programmatic backgrounding or exit in App Store apps. This package provides:
exitApp()viaexit(0)— works, but risks App Store rejection for consumer apps. Safe for enterprise/kiosk/dev builds.sendToBackground()via a privateUIApplicationselector. It has been stable across iOS releases, but it is not in the public headers, Apple does not guarantee it, and private-API use can itself be grounds for rejection. The call is guarded withrespondsToSelector:and no-ops with a warning if the selector ever disappears. Treat this as a deliberate trade-off, not a safe default.
For App Store consumer apps, the recommended pattern is:
// Show a "goodbye" screen or navigate home, then suspend
AppExit.sendToBackground();New Architecture
This package works on both architectures with no extra configuration. The JavaScript spec in src/NativeAppExit.ts drives React Native's codegen.
The two platforms get there differently, and it is worth being precise:
| Platform | Old Architecture | New Architecture |
|---|---|---|
| Android | ReactContextBaseJavaModule (src/oldarch) | codegen-generated TurboModule spec (src/newarch), selected by the IS_NEW_ARCHITECTURE_ENABLED build flag |
| iOS | RCTBridgeModule | the same RCTBridgeModule, run through React Native's interop layer |
So Android is a native TurboModule under the New Architecture; iOS is a bridge module that the New Architecture hosts via interop. Both work, and the JS API is identical — but iOS does not currently implement the codegen-generated ObjC++ spec directly. Contributions welcome.
Common use cases
Logout button that wipes state and exits:
async function handleLogout() {
await clearUserSession();
AppExit.exitApp();
}Kiosk reset button:
function KioskResetButton() {
return (
<Pressable onPress={() => AppExit.exit()}>
<Text>Reset Kiosk</Text>
</Pressable>
);
}Minimize button (Android UX pattern):
function MinimizeButton() {
return (
<Pressable onPress={() => AppExit.sendToBackground()}>
<Text>Go to Home</Text>
</Pressable>
);
}Hardware back button on Android to background instead of exit:
import { BackHandler } from 'react-native';
useEffect(() => {
const sub = BackHandler.addEventListener('hardwareBackPress', () => {
AppExit.sendToBackground();
return true; // prevent default back behavior
});
return () => sub.remove();
}, []);License
MIT © 2025 pixelcube
Contributing
Issues and PRs welcome at github.com/yashpyraj/rn-app-exit.
