flutter_permission_auto_return 0.0.2
flutter_permission_auto_return: ^0.0.2 copied to clipboard
Wrapper around permission_handler that adds automatic return-to-app on Android after the user grants special permissions from the system Settings page (e.g. all-files access, overlay, location-always).
flutter_permission_auto_return #
A drop-in wrapper around permission_handler that
automatically returns the user back to your app on Android after they grant a permission from
the system Settings page.
On Android certain permissions cannot be granted via a runtime dialog and instead require the user to flip a switch in Settings — for example All files access, Display over other apps, Schedule exact alarms, Background location, or any runtime permission that has been permanently denied. Sending users into Settings is awkward because they then have to manually navigate back. This plugin polls the system for the granted state, and as soon as the toggle flips on, it brings your app back to the foreground.
On iOS the package is a thin re-export of permission_handler — iOS does not allow apps to come
back to the foreground from Settings programmatically, so the auto-return behavior is Android-only.
Demo #

Features #
- Re-exports the entire
permission_handlerAPI — keep usingPermission.camera.request(),PermissionStatus,openAppSettings(), etc. Nothing breaks. - Adds
Permission.requestWithAutoReturn()— a single call that:- shows the runtime dialog for normal permissions,
- opens the right Settings page for "special" Android permissions,
- opens the app details page when a permission is permanently denied,
- polls the system every 500 ms until the permission is granted,
- automatically pulls your app back to the foreground.
- Works with any launcher Activity — no need to know your
MainActivityclass name. - Polling stops automatically after 5 minutes, when the engine detaches, or when you call
cancelPermissionAutoReturn().
Installation #
dependencies:
flutter_permission_auto_return: ^0.0.1
flutter pub get
You do not need to add permission_handler separately — it is re-exported by this package.
Setup #
Declare the permissions you actually use in your app's AndroidManifest.xml and iOS Info.plist,
exactly as you would for permission_handler. See the
permission_handler setup guide for the full
list. A starter set covering the cases this plugin specifically handles:
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<!-- ios/Runner/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Why you need the camera.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Why you need always-on location.</string>
Usage #
import 'package:flutter_permission_auto_return/flutter_permission_auto_return.dart';
Future<void> requestAllFilesAccess() async {
final status = await Permission.manageExternalStorage.requestWithAutoReturn();
if (status.isGranted) {
// user toggled "All files access" ON in Settings, app is back in foreground
}
}
Future<void> requestCamera() async {
// Normal runtime permission. If the user has previously denied it twice, the
// plugin will open the app details page and auto-return when granted.
final status = await Permission.camera.requestWithAutoReturn();
}
The full permission_handler API is still available on the imported Permission, so you can mix
and match:
final status = await Permission.notification.status;
if (status.isDenied) await openAppSettings();
Cancelling an in-flight request #
If your screen is disposed while the user is still in Settings, cancel the polling so the future completes and resources are released:
@override
void dispose() {
cancelPermissionAutoReturn();
super.dispose();
}
Supported permissions #
requestWithAutoReturn() is an extension on Permission, so you can call it on every
permission that permission_handler exposes — Permission.camera, Permission.contacts,
Permission.photos, anything. The runtime dialog and status checks always work, identical to
calling request() directly.
What this plugin adds on top is the auto-return-from-Settings behavior, which has two flavors on Android:
Special permissions — open dedicated Settings page #
These permissions cannot be granted via a runtime dialog at all; the user has to flip a switch in a system Settings page. The plugin opens the right page directly and watches for the toggle.
| Permission | Settings page opened |
|---|---|
manageExternalStorage |
All files access |
systemAlertWindow |
Display over other apps |
requestInstallPackages |
Install unknown apps |
scheduleExactAlarm |
Alarms & reminders (Android 12+) |
ignoreBatteryOptimizations |
Battery optimization |
accessNotificationPolicy |
Do Not Disturb access |
locationAlways |
App details (then Allow all the time) |
Runtime permissions — auto-return on permanent denial #
These go through the normal runtime dialog. If the user has previously denied them twice and the
status is permanentlyDenied, the plugin opens the app details page and watches for the user to
toggle the permission on.
camera, microphone, location, locationWhenInUse, contacts, phone, sms, storage,
photos, videos, audio, notification, calendar, calendarFullAccess,
calendarWriteOnly, sensors, sensorsAlways, bluetooth, bluetoothScan, bluetoothConnect,
bluetoothAdvertise, nearbyWifiDevices, activityRecognition, accessMediaLocation.
iOS-only permissions #
speech, mediaLibrary, photosAddOnly, reminders, appTrackingTransparency,
criticalAlerts, assistant, backgroundRefresh — these go through permission_handler
unchanged. iOS does not support programmatic foreground return, so auto-return is a no-op on iOS.
If you call
requestWithAutoReturn()on an Android permission that isn't in either of the two tables above and it ends uppermanentlyDenied, the plugin falls back topermission_handler'sopenAppSettings()without polling. You will need to detect the grant yourself viaAppLifecycleState.resumed.
How it works #
Dart: Permission.manageExternalStorage.requestWithAutoReturn()
└─► MethodChannel("openSettingsAndAutoReturn", { permission: "manageExternalStorage" })
Android (FlutterPermissionAutoReturnPlugin):
startActivity(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
Handler(mainLooper).postDelayed(check, 500)
check:
if Environment.isExternalStorageManager():
startActivity(launchIntentForPackage(packageName)) with
FLAG_ACTIVITY_NEW_TASK | CLEAR_TOP | SINGLE_TOP | EXCLUDE_FROM_RECENTS
result.success(true)
else if elapsed > 5min:
result.success(false)
else:
repeat in 500ms
FAQ #
Does this work with Flutter add-to-app?
Yes — the plugin uses getLaunchIntentForPackage() to bring the app back, which works with any
launcher Activity registered in your manifest.
What about iOS?
iOS apps cannot programmatically return to the foreground from the Settings app. On iOS,
requestWithAutoReturn() is a passthrough to Permission.request(). The user has to navigate
back manually. Listen to AppLifecycleState.resumed to refresh permission status.
Can I have two auto-return flows in flight?
No. Starting a second request cancels the first; the first call's future resolves to
PermissionStatus.denied.
Contributing #
Issues and pull requests are welcome at https://github.com/lequangkydev/flutter_permission_auto_return.
License #
MIT — see LICENSE.