package

App Update Manager

A comprehensive Flutter package for managing app updates across Play Store, App Store, and custom backends with flexible update strategies.

App Update Manager Logo

A comprehensive Flutter package for managing app updates across Play Store, App Store, and custom backends with flexible update strategies, background checks, and beautiful UI.

pub: v1.0.2License: MITPlatform: All

Features#

Multi-Platform Support

  • ✅ Android (Play Store with in-app updates)
  • ✅ iOS (App Store)
  • ✅ Custom backend API
  • ✅ Windows, macOS, Linux (custom updates)

🎯 Update Strategies

  • Flexible Updates - User can dismiss and update later
  • Immediate Updates - Blocks app usage until updated
  • Optional Updates - Shows notification but allows continued use

🎨 Customizable UI

  • Beautiful dialogs and bottom sheets
  • Fully customizable colors, text, and icons
  • Dark mode support
  • Material 3 design

🚀 Advanced Features

  • Background update checks with WorkManager
  • Version caching to reduce API calls
  • Release notes display
  • File size information
  • Force updates for critical versions
  • Minimum supported version enforcement
  • Regional rollouts support
  • A/B testing capabilities
  • Analytics integration
  • Network connectivity handling (WiFi-only option)

Installation#

Add this to your pubspec.yaml:

dependencies:
  app_update_manager: ^1.0.0

Platform-Specific Setup#

Android#

Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

iOS#

Add to ios/Runner/Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Quick Start#

Basic Usage#

import 'package:app_update_manager/app_update_manager.dart';
 
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
 
  // Initialize
  await AppUpdateManager.initialize(
    config: UpdateConfig(
      playStoreId: 'com.yourapp.package',
      appStoreId: '123456789',
      customUpdateUrl: 'https://api.yourapp.com/version',
    ),
  );
 
  runApp(MyApp());
}
 
// Check for updates
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await AppUpdateManager.checkAndShowUpdate(
              context: context,
            );
          },
          child: Text('Check for Updates'),
        ),
      ),
    );
  }
}

Custom Backend API#

Your backend should return JSON in this format:

{
  "latest_version": "1.2.0",
  "current_version": "1.0.0",
  "release_notes": "Bug fixes and improvements",
  "download_url": "https://...",
  "is_forced": false,
  "is_critical": false,
  "minimum_supported_version": "1.0.0",
  "file_size_bytes": 25600000,
  "release_date": "2024-01-15T10:30:00Z"
}

Query parameters sent to your API:

  • platform - Operating system (android, ios, etc.)
  • current_version - Current app version
  • build_number - Current build number
  • package_name - App package name
  • region - Region code (if configured)
  • test_group - A/B test group (if configured)

Custom UI#

await AppUpdateManager.checkAndShowUpdate(
  context: context,
  useBottomSheet: true,
  uiConfig: UpdateUIConfig(
    title: 'New Version Available! 🎉',
    message: 'Update to get the latest features',
    updateButtonText: 'Update Now',
    laterButtonText: 'Maybe Later',
    primaryColor: Colors.purple,
    showReleaseNotes: true,
    showFileSize: true,
    customIcon: Icon(Icons.rocket_launch),
  ),
);

Background Checks#

await AppUpdateManager.initialize(
  config: UpdateConfig(
    // ... other config
    enableBackgroundCheck: true,
    backgroundCheckInterval: 24, // hours
    wifiOnly: true, // Only check on WiFi
  ),
);
 
// Check if background update was found
final hasUpdate = await AppUpdateManager.hasBackgroundUpdate();

Force Updates#

await AppUpdateManager.initialize(
  config: UpdateConfig(
    // ... other config
    strategy: UpdateStrategy.immediate, // Force immediate update
  ),
);

Analytics Integration#

await AppUpdateManager.initialize(
  config: UpdateConfig(
    // ... other config
    enableAnalytics: true,
    onAnalyticsEvent: (event, data) {
      // Send to your analytics service
      FirebaseAnalytics.instance.logEvent(
        name: 'app_update_${event.name}',
        parameters: data,
      );
    },
  ),
);

Configuration Options#

UpdateConfig#

ParameterTypeDescriptionDefault
playStoreIdString?Android package namenull
appStoreIdString?iOS app IDnull
customUpdateUrlString?Custom API endpointnull
customHeadersMap<String, String>?HTTP headers for APInull
strategyUpdateStrategyUpdate strategyflexible
backgroundCheckIntervalintHours between checks24
enableBackgroundCheckboolEnable background checkingfalse
showDialogAutomaticallyboolAuto-show dialogtrue
enableCachingboolCache version infotrue
cacheDurationintCache duration (hours)6
requestTimeoutintAPI timeout (seconds)30
wifiOnlyboolCheck only on WiFifalse
regionCodeString?Region for rolloutsnull
testGroupString?A/B test groupnull
enableAnalyticsboolEnable analyticsfalse

UpdateUIConfig#

ParameterTypeDescription
titleString?Dialog title
messageString?Dialog message
updateButtonTextString?Update button text
cancelButtonTextString?Cancel button text
laterButtonTextString?Later button text
backgroundColorColor?Background color
primaryColorColor?Primary color
titleStyleTextStyle?Title text style
messageStyleTextStyle?Message text style
showReleaseNotesboolShow release notes
showFileSizeboolShow file size
customIconWidget?Custom icon widget

API Reference#

AppUpdateManager#

// Initialize the manager
static Future<void> initialize({required UpdateConfig config})
 
// Check for updates
static Future<UpdateInfo?> checkForUpdate()
 
// Check and show update dialog
static Future<bool> checkAndShowUpdate({
  required BuildContext context,
  UpdateUIConfig? uiConfig,
  bool useBottomSheet = false,
})
 
// Get current version
static Future<String> getCurrentVersion()
 
// Clear cache
static Future<void> clearCache()
 
// Cancel background checks
static Future<void> cancelBackgroundChecks()
 
// Check for background update
static Future<bool> hasBackgroundUpdate()

Examples#

Check the /example folder for complete examples:

  • basic_usage_example.dart - Simple implementation
  • custom_backend_example.dart - Custom API integration
  • advanced_usage_example.dart - All features showcase

Testing#

// For testing, you can mock update scenarios
final testUpdateInfo = UpdateInfo(
  latestVersion: AppVersion.parse('2.0.0'),
  currentVersion: AppVersion.parse('1.0.0'),
  releaseNotes: 'Test update',
  isForced: false,
);
 
await showUpdateDialog(
  context: context,
  updateInfo: testUpdateInfo,
);

Troubleshooting#

Android in-app update not working:

  • Ensure your app is published on Play Store (internal testing track works)
  • The update must be available on Play Store
  • Test on a real device, not emulator

iOS App Store link not opening:

  • Verify your App Store ID is correct
  • Ensure url_launcher can open App Store URLs

Background checks not working:

  • Verify workmanager is properly initialized
  • Check Android battery optimization settings
  • iOS has strict background execution limits

Contributing#

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

License#

This project is licensed under the MIT License - see the LICENSE file for details.

Support#

For issues, feature requests, or questions:

  • Open an issue on GitHub

Changelog#

See CHANGELOG.md for version history.