force_updater
Smart app version manager for Flutter.
Force update walls · Soft update banners · Maintenance mode — in 2 lines of code with 6 stunning premium layouts.
✅ Zero dependencies ✅ Material 3 ✅ No backend needed (optional) ✅ iOS App Store auto-check ✅ 6 Premium Visual Themes
🚀 Why force_updater?
Most apps break when users stay on old versions. force_updater gives you full control:
| Scenario | What happens |
|---|---|
User on 1.x, your min is 2.0 |
🔴 Force Update — blocking dialog, can't dismiss |
User on 2.0, latest is 2.1 |
🟡 Soft Update — gentle dismissible dialog |
| You're doing server maintenance | 🔧 Maintenance Screen — full-page takeover |
| Everything is fine | ✅ App loads normally — zero overhead |
📦 Installation
dependencies:
force_updater: ^1.0.0
Then run:
flutter pub get
⚡ Quickstart (2 lines!)
import 'package:force_updater/force_updater.dart';
void main() {
runApp(
ForceUpdater(
currentVersion: '1.0.0',
config: UpdateConfig.remote('https://yoursite.com/version.json'),
child: MyApp(),
),
);
}
That's it. Seriously. 🎉
🎨 Premium UI Themes (5 Dialog Styles & Maintenance Screen)
force_updater features 5 stunning, modern, pre-built update dialogs plus 1 dedicated, high-end full-page Maintenance Screen that match your brand identity out of the box. No manual design or custom overlay coding is required!
Simply toggle the update dialog style using the dialogStyle parameter:
ForceUpdater(
currentVersion: '1.0.0',
dialogStyle: UpdateDialogStyle.glassmorphism, // Choose from the 5 premium dialog layouts!
config: UpdateConfig.remote('...'),
child: MyApp(),
)
1. 🧪 Glassmorphism
- Identifier:
UpdateDialogStyle.glassmorphism(Default) - Aesthetics: Premium glass-morphism overlay featuring frosted backing, high-end blurs (
ImageFilter.blur), a glowing circular gradient rocket icon, and smooth interactive buttons. - Best For: Tech, crypto, premium SaaS, and forward-looking designer apps.
- Screenshot Preview:

🏛️ 2. Classic
- Identifier:
UpdateDialogStyle.classic - Aesthetics: Solid Material 3 cards with precise surface colors, neat primary containers, and explicit status badges.
- Best For: Enterprise software, utility apps, and traditional corporate apps.
- Screenshot Preview:

📐 3. Minimalist
- Identifier:
UpdateDialogStyle.minimalist - Aesthetics: Clean typographic outlines, thin high-contrast borders, bold monospace spacing, and simplified details without complex icons.
- Best For: Portfolio sites, developer tools, monochrome/dark apps, and minimalist brands.
- Screenshot Preview:

🎨 4. Gradient Card
- Identifier:
UpdateDialogStyle.gradient - Aesthetics: Vibrant, full-width colored cards (Indigo to Purple linear gradient), glowing icons, white typography, and custom borders.
- Best For: E-commerce, lifestyle, entertainment, and social apps that demand attention.
- Screenshot Preview:

📱 5. BottomSheet Card
- Identifier:
UpdateDialogStyle.bottomSheet - Aesthetics: A beautiful, compact slide-up sheet emerging from the bottom with dynamic drag indicator handles, perfect for keeping critical features viewable in the background.
- Best For: Messaging apps, map utilities, and modern content platforms.
- Screenshot Preview:

🔧 6. Maintenance Screen
- Identifier / Component:
MaintenanceScreen/maintenanceScreenparameter inForceUpdater - Aesthetics: Premium full-page blocking screen featuring a smooth elastic scale entrance animation, matching Material 3 color schemes, beautiful centered typography, and an active bouncing triple-dot loading indicator to reassure users.
- Best For: Lockouts during server maintenance, scheduled downtime, database migrations, or offline mode updates.
- Screenshot Preview:

🔧 Three Config Modes
Mode 1 — UpdateConfig.store() · No backend needed!
Uses Apple's free iTunes Lookup API for iOS — no server required.
ForceUpdater(
currentVersion: '1.0.0',
config: UpdateConfig.store(
iosAppId: '123456789', // From App Store Connect
androidPackageId: 'com.example.app', // Auto-builds Play Store link
),
child: MyApp(),
)
💡 When a new version is live on the App Store, your users are automatically notified!
Mode 2 — UpdateConfig.remote() · Full control
Host a tiny JSON file anywhere — GitHub Pages, Firebase Hosting, a Gist — completely free options!
ForceUpdater(
currentVersion: '1.0.0',
config: UpdateConfig.remote('https://yourname.github.io/myapp/version.json'),
child: MyApp(),
)
Your version.json file:
{
"min_version": "2.0.0",
"latest_version": "2.3.1",
"force_update": false,
"maintenance": false,
"changelog": "• Bug fixes\n• New dark mode\n• Performance improvements",
"store_url_android": "https://play.google.com/store/apps/details?id=com.example.myapp",
"store_url_ios": "https://apps.apple.com/app/id123456789"
}
To trigger a force update — just update the JSON:
{ "min_version": "3.0.0", "latest_version": "3.0.0" }
To enable maintenance mode:
{ "maintenance": true, "min_version": "1.0.0", "latest_version": "1.0.0" }
🌐 Production API & Custom Backend Setup
In production, you will use UpdateConfig.remote('url') to point to a backend API or a hosted JSON file. This allows you to dynamically control update dialogs and maintenance walls instantly without releasing a new app update to the Play Store or App Store.
📄 1. The Standard JSON Schema
Your endpoint must return a Content-Type: application/json header and match the following structure:
{
"min_version": "2.0.0",
"latest_version": "2.5.0",
"force_update": false,
"maintenance": false,
"changelog": "• Ultra-premium modern UI\n• Instant Hot Reload verification\n• Layout fixes",
"store_url_android": "https://play.google.com/store/apps/details?id=com.example.myapp",
"store_url_ios": "https://apps.apple.com/app/id123456789"
}
| Field | Type | Description |
|---|---|---|
min_version |
String |
Any app with a version lower than this is immediately force-blocked (Force Update Wall). |
latest_version |
String |
The newest version live on the store. Users below this (but >= min_version) see a dismissible popup (Soft Update). |
force_update |
Boolean |
(Optional) Manually override to force block everyone below latest_version. |
maintenance |
Boolean |
Set to true to immediately block access to the entire app and display the maintenance page. |
changelog |
String? |
(Optional) Markdown/text list of what's new. If null or empty, the "What's New" card automatically hides cleanly! |
store_url_android |
String? |
Google Play Store link for the "Update Now" button. |
store_url_ios |
String? |
Apple App Store link for the "Update Now" button. |
Mode 3 — UpdateConfig.inline() · Hardcoded / Testing
No network calls. Perfect for testing or offline demo builds without launching a mock server.
ForceUpdater(
currentVersion: '1.0.0',
config: UpdateConfig.inline(
minVersion: '2.0.0',
latestVersion: '2.1.0',
forceUpdate: false,
maintenance: false,
changelog: '• New features\n• Bug fixes',
storeUrlAndroid: 'https://play.google.com/...',
storeUrlIos: 'https://apps.apple.com/...',
),
child: MyApp(),
)
🎛️ All Parameters
ForceUpdater(
// Required
currentVersion: '1.0.0', // Your app's current version
config: UpdateConfig.remote(url),
child: MyApp(),
// Optional
dialogStyle: UpdateDialogStyle.glassmorphism, // Theme style choice
storeUrl: 'https://...', // Override store URL
maintenanceScreen: MyCustomMaintenanceScreen(), // Replace default UI
checkInterval: const Duration(minutes: 15), // Auto background polling interval
checkOnResume: true, // Re-check automatically when app resumes
onVersionResolved: (info) { // Callback when check completes
print('Latest: ${info.latestVersion}');
},
onError: (error) { // Called if network check fails
print('Check failed: $error');
},
)
🎨 Custom Maintenance Screen
Use the built-in screen with custom text:
ForceUpdater(
currentVersion: '1.0.0',
config: UpdateConfig.remote(url),
maintenanceScreen: MaintenanceScreen(
title: 'Be right back!',
message: 'We are upgrading our servers. Back in 30 mins.',
icon: Icons.coffee_rounded,
contactEmail: 'support@yourapp.com',
),
child: MyApp(),
)
Or pass any Widget for complete custom UI:
maintenanceScreen: MyFullyCustomWidget(),
- Screenshot Preview:

🛠️ Building a Completely Custom UI Notification
If you wish to bypass force_updater's 5 pre-built premium update dialogs and implement your own bespoke in-app alert, sliding drawer, or overlay banner:
- Set
showDefaultDialogtofalseinForceUpdaterto suppress all default dialog triggers. - Place your custom UI presentation logic inside the
onVersionResolvedcallback where the completedVersionInfometadata is successfully resolved.
📝 Implementation Example:
ForceUpdater(
currentVersion: '1.0.0',
showDefaultDialog: false, // <-- Disables all built-in dialog overlays!
config: UpdateConfig.remote('https://yoursite.com/version.json'),
onVersionResolved: (VersionInfo info) {
// Write your custom UI triggers here!
// 1. Check for blocking Force Update Wall
if (Semver.isLessThan('1.0.0', info.minVersion)) {
showMyCustomBlockingDialog(context, info);
}
// 2. Check for optional Soft Update Banner
else if (Semver.isLessThan('1.0.0', info.latestVersion)) {
showMyCustomInAppNotificationBanner(context, info);
}
},
child: MyApp(),
)
💡 Pro Tips
Get current version dynamically
# pubspec.yaml
dependencies:
package_info_plus: ^8.0.0
import 'package:package_info_plus/package_info_plus.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final packageInfo = await PackageInfo.fromPlatform();
runApp(
ForceUpdater(
currentVersion: packageInfo.version, // ← dynamic!
config: UpdateConfig.remote('https://yoursite.com/version.json'),
child: MyApp(),
),
);
}
Dynamic DX updates
When utilizing ForceUpdater's interactive modes in your playground, switching dialogStyle on the fly will automatically reset the dismissed cache of your dialog, showing the update layout immediately for rapid iteration.
🏗️ Architecture
force_updater/
├── lib/
│ ├── force_updater.dart # Main export
│ └── src/
│ ├── config/
│ │ └── update_config.dart # 3-mode config
│ ├── models/
│ │ └── version_info.dart # Data model
│ ├── services/
│ │ ├── semver.dart # Version comparison (pure Dart)
│ │ └── version_fetcher.dart# HTTP + iTunes API
│ └── widgets/
│ ├── force_updater_widget.dart # Main widget
│ ├── update_dialog.dart # Material 3 dialog
│ └── maintenance_screen.dart # Full-page screen
❓ FAQ
Q: Does this work offline?
A: If the version check fails (no internet), the app loads normally. Users are never blocked by a network failure.
Q: Can I customize the dialog UI?
A: The dialog uses your app's Material 3 theme automatically. We provide 5 elegant templates (dialogStyle), but for full custom overlays, use onVersionResolved to receive VersionInfo and trigger your own custom builders!
Q: Does this support Android version checking without a backend?
A: Play Store has no free official version API. For Android version gating, use UpdateConfig.remote() with a free host. UpdateConfig.store() provides the Play Store link for Android, but can't compare versions.
Q: How do I force ALL users to update?
A: Set min_version equal to your latest version in your JSON.
📜 Changelog
See CHANGELOG.md.
📄 License
MIT — see LICENSE.
🐛 Bug Reports & Support
If you encounter any issues, find a bug, or want to suggest a new feature, feel free to report it at: 👉 Yash Dodani - Bug Reports & Support
Made with ❤️ by Yash Dodani
If this package saved you time, please ⭐ it on pub.dev!