smart_permission_flow 0.0.2
smart_permission_flow: ^0.0.2 copied to clipboard
A Flutter package that provides elegant and user-friendly permission request flows built on top of permission_handler.
Smart Permission Flow #
smart_permission_flow is a Flutter package for building polished, user-friendly permission request flows on top of permission_handler.
It helps apps explain why a permission is needed, request one or more permissions, handle denied states, guide permanently denied users to settings, and keep permission UX consistent across Android and iOS.
Features #
- Beginner-friendly API for single and multi-permission flows
- Modern Material 3 bottom sheet UI
- Camera, location, microphone, notification, photos, and storage support
- Explanation UI before permission requests
- Retry flow for denied permissions
- Open Settings flow for permanently denied permissions
- Android and iOS friendly default copy
- Dark mode aware styling
- Custom button labels, colors, and sheet shape
- Fully null-safe Dart API
Why This Package Exists #
Mobile permission flows are easy to get wrong. Users need context before the system prompt appears, and apps need a reliable path for denied and permanently denied states.
smart_permission_flow keeps that behavior in one small package so product teams can ship a more respectful permission experience without rebuilding the same UX in every app.
Installation #
Add the package to your pubspec.yaml:
dependencies:
smart_permission_flow: ^0.0.1
Then run:
flutter pub get
Usage #
Import the package:
import 'package:smart_permission_flow/smart_permission_flow.dart';
Single Permission Example #
final result = await SmartPermissionFlow.request(
context,
permissions: [
SmartPermission.camera(
reason: 'Camera access is required to capture profile photos.',
),
],
);
if (result.allGranted) {
// Continue with the camera feature.
}
Multiple Permission Example #
await SmartPermissionFlow.request(
context,
permissions: [
SmartPermission.camera(
reason: 'Camera access is required to upload a profile photo.',
),
SmartPermission.location(
reason: 'Location access is required to show nearby stores.',
),
],
onAllGranted: () {
// Continue when every requested permission is available.
},
);
Result Handling Example #
final result = await SmartPermissionFlow.request(
context,
permissions: [
SmartPermission.notification(
reason: 'Notification access is required to send order updates.',
),
],
);
if (result.hasPermanentlyDeniedPermissions) {
// The package has shown an Open Settings action.
} else if (result.hasDeniedPermissions) {
// The user declined one or more permissions.
} else {
// All requested permissions were granted.
}
Customization Example #
await SmartPermissionFlow.request(
context,
permissions: [
SmartPermission.microphone(
title: 'Voice Recording',
reason: 'Microphone access is required to record voice notes.',
),
],
options: SmartPermissionFlowOptions(
continueButtonText: 'Allow Access',
retryButtonText: 'Try Again',
openSettingsButtonText: 'Open App Settings',
cancelButtonText: 'Maybe Later',
doneButtonText: 'Start Using Feature',
primaryColor: Colors.indigo,
successColor: Colors.green,
warningColor: Colors.orange,
sheetBackgroundColor: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.vertical(top: Radius.circular(36)),
primaryButtonStyle: FilledButton.styleFrom(
minimumSize: const Size.fromHeight(56),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18),
),
),
titleTextStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w900,
),
),
);
Android Setup #
Add only the permissions your app requests to 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_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Notes:
POST_NOTIFICATIONSis required for Android 13 and newer.READ_MEDIA_IMAGESis used on modern Android versions for photo access.READ_EXTERNAL_STORAGEis only needed for older Android storage flows.- Keep your Android compile SDK compatible with the version required by
permission_handler.
iOS Setup #
Add the relevant usage descriptions to ios/Runner/Info.plist.
<key>NSCameraUsageDescription</key>
<string>Camera access is required to capture profile photos.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is required to show nearby stores.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required to record audio.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to choose images.</string>
For notifications, configure Apple notification capabilities as required by your app and platform target.
Screenshots #
Preview the compact permission flow and example app:
| Example | Camera | Multiple | Notifications | Settings |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
API Overview #
SmartPermissionFlow.request #
Starts the permission flow and returns a Future<SmartPermissionResult>.
SmartPermission #
Defines a permission request with a type, title, reason, and icon.
Named constructors:
SmartPermission.cameraSmartPermission.locationSmartPermission.microphoneSmartPermission.notificationSmartPermission.photosSmartPermission.storage
SmartPermissionResult #
Contains:
allGrantedgrantedPermissionsdeniedPermissionspermanentlyDeniedPermissions
SmartPermissionFlowOptions #
Controls presentation and labels:
skipExplanationuseBottomSheetbarrierDismissibleshowSuccessStatecontinueButtonTextretryButtonTextopenSettingsButtonTextcancelButtonTextdoneButtonTextprimaryColorsuccessColorwarningColorsheetBackgroundColoriconBackgroundColorborderRadiusprimaryButtonStylesecondaryButtonStyletitleTextStylemessageTextStylepermissionTitleTextStylepermissionDescriptionTextStyle
Example App #
Run the example app from the package root:
cd example
flutter pub get
flutter run
The example includes camera, location, notification, and multiple-permission demos with result feedback.
Publishing #
Before publishing:
dart format .
flutter analyze
flutter test
flutter pub publish --dry-run
When the dry run is clean:
flutter pub publish
Update the homepage, repository, and issue_tracker fields in pubspec.yaml to point to the real project URLs before publishing.
Roadmap #
- Additional theme hooks for custom app design systems
- Optional inline permission cards
- Localized default permission copy
- Screenshot assets for pub.dev
- More platform-specific guidance for Android photo and media permissions
Contributing #
Contributions are welcome. Please open an issue for bug reports, feature requests, and API discussions. Pull requests should include tests for behavior changes and keep the public API beginner-friendly.
License #
MIT License. See LICENSE for details.





